/*
 * zLock.c
 * 
 * The Zen API 
 * Copyright (C) 2008-2009 by LMI Technologies Inc.
 * 
 * Licensed under The MIT License.
 * Redistributions of files must retain the above copyright notice.
 */ 
#include <z/zzLock.h>

#if defined(ZAPI_WINDOWS)

ZAPI_EXPORT(zStatus) zLock_Construct(zLock* lock)
{
    zLockClass* obj = zNULL;  

    zCHECK(zCalloc(&obj, 1, sizeof(zLockClass))); 

    InitializeCriticalSection(&obj->lock);
    zHANDLE(lock, obj); 

    return zOK; 
}

ZAPI_EXPORT(zStatus) zLock_Destroy(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 
    
    if (!zIS_NULL(obj))
    {
        DeleteCriticalSection(&obj->lock); 
        zCHECK(zFree(obj)); 
    }

    return zOK; 
}

ZAPI_EXPORT(zStatus) zLock_Enter(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 

    EnterCriticalSection(&obj->lock);

    return zOK;
}

ZAPI_EXPORT(zStatus) zLock_Exit(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 

    LeaveCriticalSection(&obj->lock);

    return zOK;
}

#elif defined(ZAPI_LINUX)

ZAPI_EXPORT(zStatus) zLock_Construct(zLock* lock)
{
    zLockClass* obj = zNULL;
    zStatus exception; 
    pthread_mutexattr_t mutexattr; 
  
    zEXCEPT_TRY
    {
        zEXCEPT_CHECK(zCalloc(&obj, 1, sizeof(zLockClass))); 
         
        zEXCEPT_CHECK(pthread_mutexattr_init(&mutexattr) == 0); 
        zEXCEPT_CHECK(pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE) == 0);
        zEXCEPT_CHECK(pthread_mutex_init(&obj->lock, &mutexattr) == 0);
        zEXCEPT_CHECK(pthread_mutexattr_destroy(&mutexattr) == 0);
        
        zHANDLE(lock, obj); 
    }
    zEXCEPT_CATCH(&exception) 
    {
        if (!zIS_NIL(obj))
        {
            pthread_mutex_destroy(&obj->lock);
            zFree(obj); 
        }
        zEXCEPT_SET(exception); 
    }
    zEXCEPT_FINALLY
    {
        zEXCEPT_CLOSE(); 
    }
    return zOK; 
}

ZAPI_EXPORT(zStatus) zLock_Destroy(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 
    
    zCHECK(pthread_mutex_destroy (&obj->lock) == 0);
    zCHECK(zFree(obj)); 

    return zOK; 
}

ZAPI_EXPORT(zStatus) zLock_Enter(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 

    zCHECK(pthread_mutex_lock(&obj->lock) == 0);

    return zOK;
}

ZAPI_EXPORT(zStatus) zLock_Exit(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 

    zCHECK(pthread_mutex_unlock(&obj->lock) == 0);

    return zOK;
}

ZAPI_EXPORT(pthread_mutex_t) zLock_Handle(zLock lock)
{
    zLockClass* obj = zHANDLE_POINTER(lock); 

    return obj->lock;
} 

#endif
