NAME

smartLockCreate - Creates a smart lock.

SYNOPSIS

#include <game-carrier/server.h>

typedef GCT_INTPTR (GC_CORE_API *SmartLockCreate)(void);

typedef struct smartLockCreate {
    /* ... Some fields ... */
    SmartLockCreate smartLockCreate;
    /* ... Some fields ... */
}

RETURN VALUE

Returns a newly created smart lock handle, or 0 if an error occurred.

DESCRIPTION

The smartLockCreate function creates a smart lock. It is used to protect critical sections of code from concurrent access.

The smart lock is initialized in an unlocked state.

Smart locks provide cross platform way to operate with mutexes. It can be useful for interactring between different programming languages.

Released smart locks handles can be reallocated again only after a timeout. It helps to prevent races if an object associated with a smart lock is destroyed.

EXAMPLE

#include <game-carrier/server.h>

#include <errno.h>
#include <stddef.h>
#include <stdlib.h>

static struct core_api api;

struct dlist {
    struct dlist * prev;
    struct dlist * next;
};

GCT_INTPTR primary_lock;
struct dlist root;

struct connection_data {
    GCT_INTPTR handle;
    GCT_INTPTR lock;
    struct dlist link;
    /* User data asociated with connection */
};

static struct connection_data * get_owner(struct dlist * link)
{
    if (link == &root) {
        return NULL;
    }
    intptr_t address = (intptr_t) link;
    address -= offsetof(struct connection_data, link);
    return (void*) address;
}

GC_ADAPTER_EVENT
int adapter_initialize(int id, struct core_api *core_api, const void *load_path)
{
    api = *core_api;
    primary_lock = api.smartLockCreate();
    if (primary_lock == 0) {
        return ENOMEM;
    }
    root.next = &root;
    root.prev = &root;
    return 0;
}

GC_ADAPTER_EVENT
void adapter_finalize(GCT_INT id)
{
    api.smartLockDestroy(primary_lock);
}

GC_ADAPTER_EVENT
GCT_INTPTR on_connect(
    GCT_INT app_id,
    GCT_INTPTR handle,
    GCT_INT pid,
    GCT_CSTR rip,
    GCT_INT rport,
    GCT_CSTR lip,
    GCT_INT lport,
    GCT_CSTR udata)
{
    /* Allocate user data */
    struct connection_data * conn = malloc(sizeof(struct connection_data));
    if (conn == NULL) {
        return GC_DROP_CONNECTION;
    }

    /* Create a connection lock */
    GCT_INTPTR lock = api.smartLockCreate();
    if (lock == 0) {
        free(conn);
        return GC_DROP_CONNECTION;
    }

    /* Initialize user data */
    conn->handle = handle;
    conn->lock = lock;

    /* Insert conn to a global list */
    /* Lock result is not checked for global locks.*/
    api.smartLock(primary_lock);
    conn->link.next = root.next;
    conn->link.prev = &root;
    root.next->prev = &conn->link;
    root.next = &conn->link;
    api.smartUnlock(primary_lock);

    /* Return user data */
    return (GCT_INTPTR)conn;
}

GC_ADAPTER_EVENT
void on_disconnect(
    GCT_INTPTR user)
{
    struct connection_data * data = (struct connection_data *)user;

    /* Remove conn from a global list */
    /* Lock result is not checked for global locks. */
    api.smartLock(primary_lock);
    data->link.next->prev = data->link.prev;
    data->link.prev->next = data->link.next;
    api.smartUnlock(primary_lock);

    /* Destroy connection lock */
    api.smartLockDestroy(data->lock);

    /* Free user data */
    free(data);
}

GC_ADAPTER_EVENT
void on_message(
    GCT_INTPTR user,
    GCT_PTR data,
    GCT_SIZE len)
{
    struct connection_data * conn = (struct connection_data *)user;

    /* Get the next connection */
    /* Lock result is not checked for global locks.*/
    api.smartLock(primary_lock);
    struct connection_data * next_conn = get_owner(conn->link.next);
    GCT_INTPTR next_lock = next_conn ? next_conn->lock : 0;
    api.smartUnlock(primary_lock);

    /* Your custom logic */

    /* Your custom logic for the next connection */
    if (next_conn) {
        if (api.smartLock(next_lock) != SMART_LOCK_DESTROYED) {
            /* Next connection is not disconnected yet, do something with it */
            api.smartUnlock(primary_lock);
        }
    }
}

SEE ALSO

smartLockDestroy, smartLock, smartUnlock