NAME

smartLockDestroy - Destroys a smart lock.

SYNOPSIS

#include <game-carrier/server.h>

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

typedef struct smartLockDestroy {
    /* ... Some fields ... */
    SmartLockDestroy smartLockDestroy;
    /* ... Some fields ... */
}

Parameters:

  • lock GCT_INTPTR Smart lock handle

RETURN VALUE

None.

DESCRIPTION

The smartLockDestroy function destroys a smart lock. It should be called when the lock is no longer needed.

The lock argument is the handle of the smart lock to be destroyed. It might be created by smartLockCreate function.

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

smartLockCreate, smartLock, smartUnlock