cwLib.h/cpp, cwMutex.h/cpp : Initial commit.
This commit is contained in:
parent
c0b8f78fed
commit
dfe4ca02a1
14
Makefile
14
Makefile
@ -5,11 +5,14 @@ SRC = cwCommonImpl.cpp cwMem.cpp cwLog.cpp cwUtility.cpp
|
||||
HDR += cwFileSys.h cwText.h cwFile.h cwTime.h cwLex.h cwNumericConvert.h
|
||||
SRC += cwFileSys.cpp cwText.cpp cwFile.cpp cwTime.cpp cwLex.cpp
|
||||
|
||||
HDR += cwObject.h cwObjectTemplate.h cwTextBuf.h cwThread.h cwMpScNbQueue.h
|
||||
SRC += cwObject.cpp cwTextBuf.cpp cwThread.cpp
|
||||
HDR += cwObject.h cwObjectTemplate.h cwTextBuf.h
|
||||
SRC += cwObject.cpp cwTextBuf.cpp
|
||||
|
||||
HDR += cwWebSock.h cwWebSockSvr.h
|
||||
SRC += cwWebSock.cpp cwWebSockSvr.cpp
|
||||
HDR += cwThread.h cwMutex.h cwMpScNbQueue.h
|
||||
SRC += cwThread.cpp cwMutex.cpp
|
||||
|
||||
HDR += cwWebSock.h cwWebSockSvr.h cwLib.h
|
||||
SRC += cwWebSock.cpp cwWebSockSvr.cpp cwLib.cpp
|
||||
|
||||
HDR += cwSerialPort.h cwSerialPortSrv.h
|
||||
SRC += cwSerialPort.cpp cwSerialPortSrv.cpp
|
||||
@ -29,7 +32,8 @@ SRC += cwMdns.cpp cwEuCon.cpp cwDnsSd.cpp dns_sd/dns_sd.cpp dns_sd/dns_sd_print.
|
||||
HDR += cwIo.h cwIoTest.h
|
||||
SRC += cwIo.cpp cwIoTest.cpp
|
||||
|
||||
LIBS = -lpthread -lwebsockets -lasound
|
||||
# -ldl = dlopen,dlclose,dlsym
|
||||
LIBS = -lpthread -lwebsockets -lasound -ldl
|
||||
|
||||
WS_DIR = /home/kevin/sdk/libwebsockets/build/out
|
||||
INC_PATH = $(WS_DIR)/include
|
||||
|
304
cwLib.cpp
Normal file
304
cwLib.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
#include "cwCommon.h"
|
||||
#include "cwLog.h"
|
||||
#include "cwCommonImpl.h"
|
||||
#include "cwMem.h"
|
||||
#include "cwFileSys.h"
|
||||
#include "cwLib.h"
|
||||
|
||||
#ifdef cwLINUX
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef void* dynLibH_t;
|
||||
|
||||
bool _cmLibIsNull( dynLibH_t lh )
|
||||
{ return lh == nullptr; };
|
||||
|
||||
const char* _cmLibSysError()
|
||||
{
|
||||
const char* msg = dlerror();
|
||||
if( msg == nullptr )
|
||||
msg = "<none>";
|
||||
return msg;
|
||||
}
|
||||
|
||||
dynLibH_t _cmLibOpen( const char* libFn )
|
||||
{ return dlopen(libFn,RTLD_LAZY); }
|
||||
|
||||
const char* _cmLibClose( dynLibH_t* lH )
|
||||
{
|
||||
if( *lH != nullptr )
|
||||
{
|
||||
if( dlclose(*lH) == 0 )
|
||||
*lH = nullptr;
|
||||
else
|
||||
return dlerror();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* _cmLibSym( dynLibH_t h, const char* symLabel )
|
||||
{ return dlsym(h,symLabel); }
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace lib
|
||||
{
|
||||
typedef void* dynLibH_t;
|
||||
|
||||
typedef struct node_str
|
||||
{
|
||||
char* fn; // NULL for available nodes
|
||||
unsigned id; // kInvalidId for available nodes
|
||||
dynLibH_t dynLibH; // The platform dependent library handle
|
||||
struct node_str* link;
|
||||
} node_t;
|
||||
|
||||
typedef struct lib_str
|
||||
{
|
||||
node_t* list; // list of open libraries
|
||||
unsigned id; // next library id
|
||||
} lib_t;
|
||||
|
||||
lib_t* _handleToPtr( handle_t h )
|
||||
{ return handleToPtr<handle_t,lib_t>(h); }
|
||||
|
||||
// Given a library id return the associated node
|
||||
node_t* _libIdToNode( lib_t* p, unsigned libId )
|
||||
{
|
||||
node_t* np = p->list;
|
||||
|
||||
while( np != nullptr )
|
||||
{
|
||||
if( np->id == libId )
|
||||
return np;
|
||||
|
||||
np = np->link;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Close a library and make it's node available for reuse
|
||||
rc_t _closeLib( node_t* np )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
const char* errMsg = nullptr;
|
||||
|
||||
// tell the system to close the library
|
||||
if((errMsg = _cmLibClose( &np->dynLibH )) != nullptr )
|
||||
rc = cwLogError(kInvalidOpRC,"Library %s close failed. Error:%s.", np->fn, errMsg );
|
||||
else
|
||||
{
|
||||
// mark the node as available
|
||||
mem::release(np->fn);
|
||||
np->id = kInvalidId;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Finalize the library manager
|
||||
rc_t _finalize( lib_t* p )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
node_t* np = p->list;
|
||||
while( np!=nullptr )
|
||||
{
|
||||
node_t* n0p = np->link;
|
||||
|
||||
// close the node's library
|
||||
rc_t rc0 = _closeLib( np );
|
||||
|
||||
// store the error code
|
||||
if( rc0 != kOkRC )
|
||||
rc = rc0;
|
||||
|
||||
// release the node
|
||||
mem::release(np);
|
||||
|
||||
np = n0p;
|
||||
}
|
||||
|
||||
mem::release(p);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cw::rc_t cw::lib::initialize( handle_t& h, const char* dirStr )
|
||||
{
|
||||
rc_t rc;
|
||||
if((rc = finalize(h)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
lib_t* p = mem::allocZ<lib_t>();
|
||||
|
||||
h.set(p);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::lib::finalize( handle_t& h )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
if( !h.isValid() )
|
||||
return rc;
|
||||
|
||||
lib_t* p = _handleToPtr(h);
|
||||
if((rc = _finalize(p)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
h.clear();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::lib::open( handle_t h, const char* fn, unsigned& libIdRef )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
lib_t* p = _handleToPtr(h);
|
||||
dynLibH_t lH = _cmLibOpen(fn);
|
||||
node_t* np = p->list;
|
||||
unsigned idx = 0;
|
||||
|
||||
libIdRef = kInvalidId;
|
||||
|
||||
if( _cmLibIsNull(lH) )
|
||||
{
|
||||
// There is apparently no way to get an error code which indicates that the
|
||||
// file load attempt failed because the file was not a shared library -
|
||||
// which should not generate an error message - therefore
|
||||
// we must match the end of the the error string returned by dlerror() with
|
||||
// 'invalid ELF header'.
|
||||
const char* errMsg = _cmLibSysError();
|
||||
const char* s = "invalid ELF header";
|
||||
unsigned sn = strlen(s);
|
||||
unsigned mn = strlen(errMsg);
|
||||
|
||||
// Did this load fail because the file was not a shared library?
|
||||
if( errMsg!=nullptr && mn>sn && strcmp(errMsg+mn-sn,s)==0 )
|
||||
rc = cwLogError(kOpenFailRC,"Library load failed. No error message." ); // signal error but no error message
|
||||
else
|
||||
rc = cwLogError(kOpenFailRC,"Library load failed. System Message: %s", errMsg );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// find an available node
|
||||
while( np != nullptr )
|
||||
{
|
||||
if( np->fn == nullptr )
|
||||
break;
|
||||
|
||||
np = np->link;
|
||||
++idx;
|
||||
}
|
||||
|
||||
// no available node was found - allocate a new one
|
||||
if( np == nullptr )
|
||||
{
|
||||
np = mem::allocZ<node_t>(1);
|
||||
np->link = p->list;
|
||||
p->list = np;
|
||||
}
|
||||
|
||||
// initialize the node
|
||||
np->fn = mem::duplStr(fn);
|
||||
np->dynLibH = lH;
|
||||
np->id = p->id++;
|
||||
libIdRef = np->id;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
cw::rc_t cw::lib::close( handle_t h, unsigned libId )
|
||||
{
|
||||
lib_t* p = _handleToPtr(h);
|
||||
node_t* np;
|
||||
|
||||
// locate the library to close
|
||||
if((np = _libIdToNode(p,libId)) == nullptr )
|
||||
return cwLogError(kInvalidIdRC,"Library close failed. The library with id:%i not found.",libId);
|
||||
|
||||
return _closeLib(np);
|
||||
}
|
||||
|
||||
void* cw::lib::symbol( handle_t h, unsigned libId, const char* symName )
|
||||
{
|
||||
void* f;
|
||||
lib_t* p = _handleToPtr(h);
|
||||
node_t* np = _libIdToNode(p,libId);
|
||||
|
||||
if( (np == NULL) || _cmLibIsNull(np->dynLibH) )
|
||||
{
|
||||
cwLogError(kInvalidArgRC,"The library id %i is not valid or the library is closed.",libId);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if((f = _cmLibSym(np->dynLibH,symName)) == NULL)
|
||||
{
|
||||
cwLogError(kInvalidArgRC,"The dynamic symbol '%s' was not found. System Message: %s", cwStringNullGuard(symName), _cmLibSysError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
cw::rc_t cw::lib::scan( handle_t h, const char* dirStr )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
unsigned dirEntryN = 0;
|
||||
filesys::dirEntry_t* de = dirEntries( dirStr, filesys::kFileFsFl, &dirEntryN );
|
||||
unsigned libId;
|
||||
|
||||
for(unsigned i=0; i<dirEntryN; ++i)
|
||||
if( de[i].name != nullptr )
|
||||
if((rc = open( h, de[i].name, libId )) != kOkRC )
|
||||
cwLogWarning("The file '%s' is not a shared library.",de[i].name);
|
||||
|
||||
mem::release(de);
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned cw::lib::count( handle_t h )
|
||||
{
|
||||
lib_t* p = _handleToPtr(h);
|
||||
unsigned n = 0;
|
||||
node_t* np = p->list;
|
||||
for(; np!=nullptr; np=np->link)
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
unsigned cw::lib::indexToId( handle_t h, unsigned idx )
|
||||
{
|
||||
lib_t* p = _handleToPtr(h);
|
||||
unsigned n = 0;
|
||||
node_t* np = p->list;
|
||||
|
||||
for(; np!=nullptr; np=np->link)
|
||||
if( n == idx )
|
||||
return np->id;
|
||||
|
||||
cwLogError(kInvalidArgRC, "The library index %i is not valid.",idx);
|
||||
return kInvalidId;
|
||||
}
|
||||
|
||||
|
||||
const char* cw::lib::name( handle_t h, unsigned id )
|
||||
{
|
||||
lib_t* p = _handleToPtr(h);
|
||||
node_t* np;
|
||||
if((np = _libIdToNode(p,id)) == nullptr )
|
||||
{
|
||||
cwLogError(kInvalidArgRC,"The library associated with the the id:%i could not be found.",id);
|
||||
return nullptr;
|
||||
}
|
||||
return np->fn;
|
||||
}
|
31
cwLib.h
Normal file
31
cwLib.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef cwLib_H
|
||||
#define cwLib_H
|
||||
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace lib
|
||||
{
|
||||
typedef handle<struct lib_str> handle_t;
|
||||
|
||||
rc_t initialize( handle_t& h, const char* dirStr );
|
||||
rc_t finalize( handle_t& h );
|
||||
// libIdRef is set to kInvalidId if rc != kOkRC
|
||||
rc_t open( handle_t h, const char* fn, unsigned& libIdRef );
|
||||
rc_t close( handle_t h, unsigned libId );
|
||||
void* symbol( handle_t h, unsigned libId, const char* symName );
|
||||
|
||||
// open all the libraries in a directory
|
||||
rc_t scan( handle_t h, const char* dir );
|
||||
|
||||
// Return the count of open libraries,
|
||||
unsigned count(handle_t h );
|
||||
unsigned indexToId( handle_t h, unsigned idx );
|
||||
|
||||
// Return the name associated with the i'th library
|
||||
const char* name( handle_t h, unsigned id );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
157
cwMutex.cpp
Normal file
157
cwMutex.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
#include "cwCommon.h"
|
||||
#include "cwLog.h"
|
||||
#include "cwCommonImpl.h"
|
||||
#include "cwMem.h"
|
||||
#include "cwMutex.h"
|
||||
#include "cwTime.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace mutex
|
||||
{
|
||||
typedef struct mutex_str
|
||||
{
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cvar;
|
||||
} mutex_t;
|
||||
|
||||
|
||||
mutex_t* _handleToPtr( handle_t h )
|
||||
{ return handleToPtr<handle_t,mutex_t>(h); }
|
||||
|
||||
rc_t _destroy( mutex_t* p )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
int sysRC;
|
||||
|
||||
if((sysRC = pthread_cond_destroy(&p->cvar)) != 0)
|
||||
cwLogSysError(kObjFreeFailRC,sysRC,"Thread condition var. destroy failed.");
|
||||
else
|
||||
if((sysRC = pthread_mutex_destroy(&p->mutex)) != 0)
|
||||
cwLogSysError(kObjFreeFailRC,sysRC,"Thread mutex destroy failed.");
|
||||
else
|
||||
mem::release(p);
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::create( handle_t& h )
|
||||
{
|
||||
rc_t rc;
|
||||
if((rc = destroy(h)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
mutex_t* p = mem::allocZ<mutex_t>();
|
||||
int sysRC;
|
||||
|
||||
if((sysRC = pthread_mutex_init(&p->mutex,NULL)) != 0 )
|
||||
cwLogSysError(kObjAllocFailRC,sysRC,"Thread mutex create failed.");
|
||||
else
|
||||
if((sysRC = pthread_cond_init(&p->cvar,NULL)) != 0 )
|
||||
cwLogSysError(kObjAllocFailRC,sysRC,"Thread Condition var. create failed.");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::destroy( handle_t& h )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
if( !h.isValid() )
|
||||
return rc;
|
||||
|
||||
mutex_t* p = _handleToPtr(h);
|
||||
if((rc = _destroy(p)) != kOkRC )
|
||||
return rc;
|
||||
|
||||
h.clear();
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::tryLock( handle_t h, bool& lockFlRef )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
mutex_t* p = _handleToPtr(h);
|
||||
int sysRc = pthread_mutex_trylock(&p->mutex);
|
||||
|
||||
switch(sysRc)
|
||||
{
|
||||
case EBUSY:
|
||||
lockFlRef = false;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
lockFlRef = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = cwLogSysError(kInvalidOpRC,sysRc,"Thread mutex try-lock failed.");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::lock( handle_t h )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
mutex_t* p = _handleToPtr(h);
|
||||
int sysRc;
|
||||
|
||||
if((sysRc = pthread_mutex_lock(&p->mutex)) != 0)
|
||||
rc = cwLogSysError(kInvalidOpRC,sysRc,"Lock failed.");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::unlock( handle_t h )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
mutex_t* p = _handleToPtr(h);
|
||||
int sysRc;
|
||||
|
||||
if((sysRc = pthread_mutex_unlock(&p->mutex)) != 0)
|
||||
return cwLogSysError(kInvalidOpRC,sysRc,"Unlock failed.");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
cw::rc_t cw::mutex::waitOnCondVar( handle_t h, bool lockThenWaitFl, unsigned timeOutMs )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
mutex_t* p = _handleToPtr(h);
|
||||
int sysRC;
|
||||
|
||||
if( lockThenWaitFl )
|
||||
if((sysRC = pthread_mutex_lock(&p->mutex)) != 0)
|
||||
return cwLogSysError(kInvalidOpRC,sysRC,"Lock failed.");
|
||||
|
||||
// if no timeout was given ....
|
||||
if( timeOutMs == 0)
|
||||
{
|
||||
// ... then wait until the cond-var is triggered
|
||||
if((sysRC = pthread_cond_wait(&p->cvar,&p->mutex)) != 0 )
|
||||
return cwLogSysError(kInvalidOpRC,sysRC,"Thread cond. var. wait failed.");
|
||||
}
|
||||
else // ... otherwise use the cond. var. wait with timeout API
|
||||
{
|
||||
|
||||
struct timespec ts;
|
||||
|
||||
if((rc = time::futureMs(ts,timeOutMs)) == kOkRC )
|
||||
if((sysRC = pthread_cond_timedwait(&p->cvar,&p->mutex,&ts)) != 0 )
|
||||
{
|
||||
if( sysRC == ETIMEDOUT )
|
||||
rc = kTimeOutRC;
|
||||
else
|
||||
return cwLogSysError(kInvalidOpRC,sysRC,"Thread cond. var. wait failed.");
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
|
||||
}
|
24
cwMutex.h
Normal file
24
cwMutex.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef cwMutex_H
|
||||
#define cwMutex_H
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace mutex
|
||||
{
|
||||
typedef handle<struct mutex_str> handle_t;
|
||||
|
||||
rc_t create( handle_t& h );
|
||||
rc_t destroy( handle_t& h );
|
||||
|
||||
rc_t tryLock( handle_t h, bool& lockFlRef );
|
||||
rc_t lock( handle_t h );
|
||||
rc_t unlock( handle_t h );
|
||||
|
||||
rc_t waitOnCondVar( handle_t h, bool lockThenWaitFl, unsigned timeOutMs );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user