#if !defined __lanes_private_h__
#define __lanes_private_h__ 1

#include "uniquekey.h"
#include "cancel.h"
#include "universe.h"

// NOTE: values to be changed by either thread, during execution, without
//       locking, are marked "volatile"
//
struct s_Lane
{
    THREAD_T thread;
    //
    // M: sub-thread OS thread
    // S: not used

    char const* debug_name;

    lua_State* L;
    Universe* U;
    //
    // M: prepares the state, and reads results
    // S: while S is running, M must keep out of modifying the state

    volatile enum e_status status;
    // 
    // M: sets to PENDING (before launching)
    // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED

    SIGNAL_T* volatile waiting_on;
    //
    // When status is WAITING, points on the linda's signal the thread waits on, else NULL

    volatile enum e_cancel_request cancel_request;
    //
    // M: sets to FALSE, flags TRUE for cancel request
    // S: reads to see if cancel is requested

#if THREADWAIT_METHOD == THREADWAIT_CONDVAR
    SIGNAL_T done_signal;
    //
    // M: Waited upon at lane ending  (if Posix with no PTHREAD_TIMEDJOIN)
    // S: sets the signal once cancellation is noticed (avoids a kill)

    MUTEX_T done_lock;
    // 
    // Lock required by 'done_signal' condition variable, protecting
    // lane status changes to DONE/ERROR_ST/CANCELLED.
#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR

    volatile enum
    {
        NORMAL,         // normal master side state
        KILLED          // issued an OS kill
    } mstatus;
    //
    // M: sets to NORMAL, if issued a kill changes to KILLED
    // S: not used

    struct s_Lane* volatile selfdestruct_next;
    //
    // M: sets to non-NULL if facing lane handle '__gc' cycle but the lane
    //    is still running
    // S: cleans up after itself if non-NULL at lane exit

#if HAVE_LANE_TRACKING()
    struct s_Lane* volatile tracking_next;
#endif // HAVE_LANE_TRACKING()
    //
    // For tracking only
};
typedef struct s_Lane Lane;

// xxh64 of string "LANE_POINTER_REGKEY" generated at https://www.pelock.com/products/hash-calculator
static DECLARE_CONST_UNIQUE_KEY( LANE_POINTER_REGKEY, 0xB3022205633743BC); // used as registry key

// To allow free-running threads (longer lifespan than the handle's)
// 'Lane' are malloc/free'd and the handle only carries a pointer.
// This is not deep userdata since the handle's not portable among lanes.
//
inline Lane* lua_toLane(lua_State* L, int i_)
{
    return *(Lane**)(luaL_checkudata(L, i_, "Lane"));
}

static inline Lane* get_lane_from_registry( lua_State* L)
{
    Lane* s;
    STACK_GROW( L, 1);
    STACK_CHECK( L, 0);
    REGISTRY_GET( L, LANE_POINTER_REGKEY);
    s = lua_touserdata( L, -1);     // lightuserdata (true 's_lane' pointer) / nil
    lua_pop( L, 1);
    STACK_END( L, 0);
    return s;
}

int push_thread_status( lua_State* L, Lane* s);


#endif // __lanes_private_h__