NAME

smartLock - Unlocks a smart lock.

SYNOPSIS

#include <game-carrier/server.h>

typedef void (GC_CORE_API *SmartUnlock)(
    GCT_INTPTR lock);

typedef struct smartUnlock {
    /* ... Some fields ... */
    SmartUnlock smartUnlock;
    /* ... Some fields ... */
}

Parameters:

  • lock GCT_INTPTR Represents the smart lock handle.

RETURN VALUE

None.

DESCRIPTION

The smartUnlock function unlocks a smart lock. It is used to release a lock acquired by smartLock function.

The lock argument is the handle of the smart lock to be unlocked. It might be created by smartLockCreate function and locked by smartLock function before.

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

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

smartLock, smartLockCreate, smartLockDestroy