int LLBC_SetConsoleColor(FILE *file, int color) { #if LLBC_TARGET_PLATFORM_NON_WIN32 LLBC_SetLastError(LLBC_ERROR_NOT_IMPL); return LLBC_FAILED; #else const int fileNo = LLBC_File::GetFileNo(file); if (UNLIKELY(fileNo == -1)) { return LLBC_FAILED; } else if (UNLIKELY(fileNo != 1 && fileNo != 2)) { LLBC_SetLastError(LLBC_ERROR_INVALID); return LLBC_FAILED; } LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock(); HANDLE handle = (fileNo == 1 ? ::GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE)); if (::SetConsoleTextAttribute(handle, color) == 0) { LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock(); LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock(); return LLBC_OK; #endif }
int LLBC_FlushFile(FILE *file) { if (UNLIKELY(!file)) { LLBC_SetLastError(LLBC_ERROR_INVALID); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 flockfile(file); if (UNLIKELY(::fflush(file) != 0)) { funlockfile(file); LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } funlockfile(file); return LLBC_OK; #else // Win32 const int fileNo = LLBC_File::GetFileNo(file); LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Lock(); if (UNLIKELY(::fflush(file) != 0)) { LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock(); LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } LLBC_INTERNAL_NS __g_consoleLock[(fileNo == 1 || fileNo == 2 ? 0 : 1)].Unlock(); return LLBC_OK; #endif }
int LLBC_GetQueuedCompletionStatus(LLBC_IocpHandle handle, void *numOfBytes, void **compKey, LLBC_POverlapped *ol, ulong milliSeconds) { BOOL ret = ::GetQueuedCompletionStatus(handle, (LPDWORD)numOfBytes, (PULONG_PTR)compKey, (LPOVERLAPPED *)ol, milliSeconds); if (ret == FALSE) { if (::GetLastError() == WAIT_TIMEOUT) { LLBC_SetLastError(LLBC_ERROR_TIMEOUT); } else { LLBC_SetLastError(LLBC_ERROR_OSAPI); } return LLBC_RTN_FAILED; } return LLBC_RTN_OK; }
LLBC_LibraryFun LLBC_GetProcAddress(LLBC_LibraryHandle handle, const char *procName) { #if LLBC_TARGET_PLATFORM_NON_WIN32 // Clear any existing error. dlerror(); void *proc = dlsym(handle, procName); if (dlerror() != NULL) { LLBC_SetLastError(LLBC_ERROR_INVALID); return NULL; } if (!proc) { LLBC_SetLastError(LLBC_ERROR_NOT_FOUND); return NULL; } return (LLBC_LibraryFun)proc; #else // LLBC_TARGET_PLATFORM_NON_WIN32 FARPROC proc = ::GetProcAddress(handle, procName); if (!proc) { LLBC_SetLastError(LLBC_ERROR_OSAPI); } return (LLBC_LibraryFun)proc; #endif // LLBC_TARGET_PLATFORM_WIN32 }
LLBC_Array::Iter LLBC_Array::Insert(LLBC_Array::Iter n0, LLBC_Array::Obj *o) { if (UNLIKELY(!o)) { LLBC_SetLastError(LLBC_ERROR_ARG); return End(); } if (!(n0 >= Begin() && n0 <= End())) { LLBC_SetLastError(LLBC_ERROR_ARG); return End(); } if (_size == _capacity) { Recapacity(MAX(1, _size * 2)); } LLBC_MemCpy(_objs + n0._idx + 1, _objs + n0._idx, (_size - n0._idx) * sizeof(Obj *)); _objs[n0._idx] = o; _objs[n0._idx]->Retain(); _size += 1; return Iter(_objs, n0._idx); }
int LLBC_KillThread(LLBC_NativeThreadHandle handle, int signo) { if (handle == LLBC_INVALID_NATIVE_THREAD_HANDLE) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = 0; if ((status = pthread_kill(handle, signo)) != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else if (raise(signo) != 0) { LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #endif }
__LLBC_NS_BEGIN LLBC_LibraryHandle LLBC_LoadLibrary(const char *fileName) { LLBC_LibraryHandle handle = LLBC_INVALID_LIBRARY_HANDLE; #if LLBC_TARGET_PLATFORM_NON_WIN32 if ((handle = dlopen(fileName, RTLD_LAZY)) == LLBC_INVALID_LIBRARY_HANDLE) { LLBC_SetLastError(LLBC_ERROR_UNKNOWN); } return handle; #else // LLBC_TARGET_PLATFORM_WIN32 // Note, WIN32 API ::GetProcAddress not support slashes(/), so replace it. LLBC_String libName(fileName); libName.findreplace(LLBC_SLASH_A, LLBC_BACKLASH_A); if (libName.empty()) libName = LLBC_Directory::ModuleFileName(); if ((handle = ::LoadLibraryExA(libName.c_str(), NULL, 0)) == LLBC_INVALID_LIBRARY_HANDLE) LLBC_SetLastError(LLBC_ERROR_OSAPI); return handle; #endif // LLBC_TARGET_PLATFORM_NON_WIN32 }
int LLBC_TlsSetValue(LLBC_TlsHandle handle, void *value) { if (handle == LLBC_INVALID_TLS_HANDLE) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = pthread_setspecific(handle, value); if (status != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else if (::TlsSetValue(handle, value) == 0) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } return LLBC_OK; #endif }
int LLBC_JoinThread(LLBC_NativeThreadHandle handle) { if (handle == LLBC_INVALID_NATIVE_THREAD_HANDLE) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = pthread_join(handle, NULL); if (status != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else if (::WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } return LLBC_OK; #endif }
int LLBC_CancelThread(LLBC_NativeThreadHandle handle) { if (handle == LLBC_INVALID_NATIVE_THREAD_HANDLE) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = 0; if ((status = pthread_cancel(handle)) != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else if (::TerminateThread(handle, 0) == 0) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } return LLBC_OK; #endif }
int LLBC_Dictionary::Insert(const LLBC_String &key, LLBC_Dictionary::Obj *o) { if (UNLIKELY(!o)) { LLBC_SetLastError(LLBC_ERROR_INVALID); return LLBC_RTN_FAILED; } if (this->Find(key) != this->End()) { LLBC_SetLastError(LLBC_ERROR_REPEAT); return LLBC_RTN_FAILED; } // Check bucket size and auto expand it. if (_size >= _bucketSize * 100) { this->SetHashBucketSize(_bucketSize * 2); } LLBC_DictionaryElem *elem = new LLBC_DictionaryElem(key, o); // Hash to bucket. elem->Hash(_bucket, _bucketSize); // Link to doubly-linked list. this->AddToDoublyLinkedList(elem); _size += 1; return LLBC_RTN_OK; }
int LLBC_ThreadManager::SetPriority(LLBC_Handle handle, int priority) { if (UNLIKELY(handle == LLBC_INVALID_HANDLE)) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } LLBC_Guard guard(_lock); LLBC_ThreadDescriptor *threadDesc = FindThreadDescriptor(handle); if (!threadDesc) { LLBC_SetLastError(LLBC_ERROR_NOT_FOUND); return LLBC_FAILED; } if (threadDesc->GetPriority() == priority) { return LLBC_OK; } int rtn = LLBC_SetThreadPriority(threadDesc->GetNativeHandle(), priority); if (rtn == LLBC_OK) { threadDesc->SetPriority(priority); } return rtn; }
int LLBC_TlsAlloc(LLBC_TlsHandle *handle) { if (!handle) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = pthread_key_create(handle, NULL); if (status != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else if ((*handle = ::TlsAlloc()) == TLS_OUT_OF_INDEXES) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } return LLBC_OK; #endif }
LLBC_Array::Iter LLBC_Array::Erase(LLBC_Array::Iter n0, LLBC_Array::Iter n1) { if (UNLIKELY(n0 >= n1)) { LLBC_SetLastError(LLBC_ERROR_ARG); return End(); } if (!(n0 >= Begin() && n0 < End()) || !(n1 >= Begin() && n1 <= End())) { LLBC_SetLastError(LLBC_ERROR_ARG); return End(); } for (difference_type i = n0._idx; i < n1._idx; i++) { _objs[i]->Release(); } LLBC_MemCpy(_objs + n0._idx, _objs + n1._idx, (_size - n1._idx) * sizeof(Obj *)); LLBC_MemSet(_objs + _size - (n1._idx - n0._idx), 0, (n1._idx - n0._idx) * sizeof(Obj *)); _size -= (n1._idx - n0._idx); LLBC_SetLastError(LLBC_ERROR_SUCCESS); return Iter(_objs, n0._idx); }
int LLBC_ThreadManager::KillGroup(LLBC_Handle handle, int signum) { if (UNLIKELY(handle == LLBC_INVALID_HANDLE)) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } LLBC_Guard guard(_lock); LLBC_ThreadGroupDescriptor *groupDesc = FindThreadGroupDescriptor(handle); if (!groupDesc) { LLBC_SetLastError(LLBC_ERROR_NOT_FOUND); return LLBC_FAILED; } LLBC_ThreadDescriptor *threadDesc = groupDesc->FindFirstThreadDescriptor(); while (threadDesc) { LLBC_ThreadDescriptor *tmpThreadDesc = threadDesc; threadDesc = threadDesc->GetGroupThreadNext(); if (Kill(tmpThreadDesc->GetHandle(), signum) != LLBC_OK) { return LLBC_FAILED; } } return LLBC_OK; }
int LLBC_ThreadManager::Kill(LLBC_Handle handle, int signum) { if (UNLIKELY(handle == LLBC_INVALID_HANDLE)) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } LLBC_Guard guard(_lock); LLBC_ThreadDescriptor *threadDesc = FindThreadDescriptor(handle); if (!threadDesc) { LLBC_SetLastError(LLBC_ERROR_NOT_FOUND); return LLBC_FAILED; } if (threadDesc->GetState() != LLBC_ThreadState::Running && threadDesc->GetState() != LLBC_ThreadState::Suspended) { LLBC_SetLastError(LLBC_ERROR_NOT_INIT); return LLBC_FAILED; } return LLBC_KillThread(threadDesc->GetNativeHandle(), signum); }
int LLBC_SetThreadPriority(LLBC_NativeThreadHandle handle, int priority) { if (handle == LLBC_INVALID_NATIVE_THREAD_HANDLE || (priority < LLBC_ThreadPriority::Begin || priority >= LLBC_ThreadPriority::End)) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } #if LLBC_TARGET_PLATFORM_NON_WIN32 int status = 0; int policy = 0; int priorityMin = 0; int priorityMax = 0; struct sched_param schedParam; if ((status = pthread_getschedparam(handle, &policy, &schedParam)) != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } priorityMin = sched_get_priority_min(policy); priorityMax = sched_get_priority_max(policy); #if LLBC_TARGET_PLATFORM_LINUX schedParam.sched_priority = LLBC_INTERNAL_NS __LLBCPriority2LinuxPriority(priority, priorityMin, priorityMax); #elif LLBC_TARGET_PLATFORM_IPHONE schedParam.sched_priority = LLBC_INTERNAL_NS __LLBCPriority2IphonePriority(priority, priorityMin, priorityMax); #elif LLBC_TARGET_PLATFORM_MAC schedParam.sched_priority = LLBC_INTERNAL_NS __LLBCPriority2MacPriority(priority, priorityMin, priorityMax); #elif LLBC_TARGET_PLATFORM_ANDROID schedParam.sched_priority = LLBC_INTERNAL_NS __LLBCPriority2AndroidPriority(priority, priorityMin, priorityMax); #endif if ((status = pthread_setschedparam(handle, policy, &schedParam)) != 0) { errno = status; LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; #else BOOL ret = ::SetThreadPriority(handle, LLBC_INTERNAL_NS __LLBCPriority2WinPriority(priority)); if (ret == FALSE) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return LLBC_FAILED; } return LLBC_OK; #endif }
int LLBC_ThreadManager::Wait(LLBC_Handle handle) { if (UNLIKELY(handle == LLBC_INVALID_HANDLE)) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_FAILED; } _lock.Lock(); LLBC_ThreadDescriptor *threadDesc = FindThreadDescriptor(handle); if (!threadDesc) { _lock.Unlock(); LLBC_SetLastError(LLBC_ERROR_NOT_FOUND); return LLBC_FAILED; } if (threadDesc->GetState() != LLBC_ThreadState::Running && threadDesc->GetState() != LLBC_ThreadState::Suspended) { _lock.Unlock(); LLBC_SetLastError(LLBC_ERROR_NOT_INIT); return LLBC_FAILED; } LLBC_NativeThreadHandle nativeHandle = threadDesc->GetNativeHandle(); _lock.Unlock(); int rtn = LLBC_JoinThread(nativeHandle); if (rtn == LLBC_OK) { LLBC_Guard guard(_lock); if ((threadDesc = FindThreadDescriptor(handle))) { #if LLBC_TARGET_PLATFORM_WIN32 if (threadDesc->GetFlags() | LLBC_ThreadFlag::Joinable) { ::CloseHandle(threadDesc->GetNativeHandle()); } #endif RemoveThreadDescriptor(handle); } } return rtn; }
LLBC_Handle LLBC_ThreadManager::CreateThread(LLBC_ThreadProc proc, LLBC_ThreadArg arg, int flags, int priority, int stackSize, LLBC_BaseTask *task, LLBC_Handle groupHandle, LLBC_NativeThreadHandle *nativeHandle, LLBC_Handle *handle) { if (!proc) { LLBC_SetLastError(LLBC_ERROR_ARG); return LLBC_INVALID_HANDLE; } LLBC_Guard guard(_lock); return CreateThread_NonLock(proc, arg, flags, priority, stackSize, task, groupHandle, nativeHandle, handle); }
void LLBC_ConditionVariable::AfterWait(LLBC_ILock &lock) { int errNo = LLBC_GetLastError(); int subErrNo = LLBC_GetSubErrorNo(); int signalsWasLeft = 0; ::EnterCriticalSection(&_cond.unblockLock); if ((signalsWasLeft = _cond.waitersToUnblock) != 0) { -- _cond.waitersToUnblock; } else if (_cond.waitersBlocked == ++ _cond.waitersGone) { ::WaitForSingleObject(_cond.blockLock, INFINITE); _cond.waitersBlocked -= _cond.waitersGone; ::ReleaseSemaphore(_cond.blockLock, 1, NULL); _cond.waitersGone = 0; } ::LeaveCriticalSection(&_cond.unblockLock); if (signalsWasLeft == 1) { ::ReleaseSemaphore(_cond.blockLock, 1, NULL); } lock.Lock(); LLBC_SetLastError(errNo); LLBC_SetSubErrorNo(subErrNo); }
int LLBC_Dictionary::SetHashBucketSize(size_type bucketSize) { if (UNLIKELY(bucketSize == 0)) { LLBC_SetLastError(LLBC_ERROR_INVALID); return LLBC_RTN_FAILED; } // Cancel hash. Iter it = this->Begin(), endIt = this->End(); for (; it != endIt; it++) { it.Elem()->CancelHash(); } // ReAlloc bucket. _bucketSize = bucketSize; _bucket = reinterpret_cast<LLBC_DictionaryElem **>( realloc(_bucket, _bucketSize * sizeof(LLBC_DictionaryElem *))); LLBC_MemSet(_bucket, 0, _bucketSize * sizeof(LLBC_DictionaryElem *)); // ReHash. it = this->Begin(); for (; it != endIt; it++) { it.Elem()->Hash(_bucket, _bucketSize); } return LLBC_RTN_OK; }
LLBC_String LLBC_GetTemporaryDirectory(bool appendSlash) { #if LLBC_TARGET_PLATFORM_NON_WIN32 if (appendSlash) { return "/tmp/"; } else { return "/tmp"; } #else DWORD bufLen = 0; bufLen = ::GetTempPathA(0, NULL); bufLen += 1; LPSTR buf = reinterpret_cast<LPSTR>(::malloc(sizeof(CHAR) * bufLen)); if (::GetTempPathA(bufLen, buf) == 0) { LLBC_SetLastError(LLBC_ERROR_OSAPI); ::free(buf); return ""; } LLBC_String path = buf; ::free(buf); if (!appendSlash) { path = path.substr(0, path.size() - 1); } return path; #endif }
LLBC_String LLBC_GetCacheDirectory(bool appendSlash) { #if LLBC_TARGET_PLATFORM_NON_WIN32 if (appendSlash) { return "/tmp/"; } else { return "/tmp"; } #else CHAR buf[MAX_PATH]; memset(buf, 0, sizeof(CHAR) * MAX_PATH); if (::SHGetSpecialFolderPathA(NULL, buf, CSIDL_INTERNET_CACHE, FALSE) == FALSE) { LLBC_SetLastError(LLBC_ERROR_OSAPI); return ""; } LLBC_String path = buf; if (appendSlash) { path.append(1, LLBC_BACKLASH_A); } return path; #endif }
LLBC_String LLBC_Directory::TempDir() { #if LLBC_TARGET_PLATFORM_NON_WIN32 return "/tmp"; #else // Win32 DWORD bufLen = 0; bufLen = ::GetTempPathA(0, NULL); bufLen += 1; LPSTR buf = reinterpret_cast<LPSTR>(::malloc(sizeof(CHAR) * bufLen)); if (::GetTempPathA(bufLen, buf) == 0) { LLBC_SetLastError(LLBC_ERROR_OSAPI); ::free(buf); return ""; } LLBC_String path = buf; ::free(buf); if (path[path.length() - 1] == LLBC_BACKLASH_A) return path.substr(0, path.length() - 1); return path; #endif // Non-Win32 }
int LLBC_IocpPoller::Start() { if (_started) { LLBC_SetLastError(LLBC_ERROR_REENTRY); return LLBC_FAILED; } if ((_iocp = LLBC_CreateIocp()) == LLBC_INVALID_IOCP_HANDLE) return LLBC_FAILED; if (StartupMonitor() != LLBC_OK) { LLBC_CloseIocp(_iocp); _iocp = LLBC_INVALID_IOCP_HANDLE; return LLBC_FAILED; } if (Activate() != LLBC_OK) { StopMonitor(); LLBC_CloseIocp(_iocp); _iocp = LLBC_INVALID_IOCP_HANDLE; return LLBC_FAILED; } _started = true; return LLBC_OK; }
__LLBC_NS_BEGIN LLBC_String LLBC_GetHomeDirectory(bool appendSlash) { #if LLBC_TARGET_PLATFORM_NON_WIN32 char *valStr = getenv("HOME"); #else char *valStr = getenv("HOMEPATH"); #endif if (!valStr) { LLBC_SetLastError(LLBC_ERROR_CLIB); return ""; } LLBC_String path = valStr; if (appendSlash) { #if LLBC_TARGET_PLATFORM_NON_WIN32 path.append(1, LLBC_SLASH_A); #else path.append(1, LLBC_BACKLASH_A); #endif } return path; }
__LLBC_INTERNAL_NS_END __LLBC_NS_BEGIN int LLBC_Startup() { if(LLBC_INTERNAL_NS __llbc_inited) { LLBC_SetLastError(LLBC_ERROR_REENTRY); return LLBC_RTN_FAILED; } if(__LLBC_CommonStartup() != LLBC_RTN_OK) { return LLBC_RTN_FAILED; } if(__LLBC_CoreStartup() != LLBC_RTN_OK) { return LLBC_RTN_FAILED; } if(__LLBC_CommStartup() != LLBC_RTN_OK) { return LLBC_RTN_FAILED; } LLBC_INTERNAL_NS __llbc_inited = true; return LLBC_RTN_OK; }
const LLBC_ISampler *LLBC_SamplerGroup::GetSampler(const LLBC_String &name) const { _SamplerMapCIter iter = _samplers->find(name); return iter != _samplers->end() ? iter->second : (LLBC_SetLastError(LLBC_ERROR_NOT_FOUND), (LLBC_ISampler *)NULL); }
int LLBC_EpollClose(LLBC_Handle epfd) { if (::close(epfd) != 0) { LLBC_SetLastError(LLBC_ERROR_CLIB); return LLBC_FAILED; } return LLBC_OK; }
int LLBC_EpollWait(LLBC_Handle epfd, LLBC_EpollEvent *events, int maxEvents, int timeout) { int ret = 0; while ((ret = epoll_wait(epfd, events, maxEvents, timeout)) < 0 && errno == EINTR); if (ret < 0) LLBC_SetLastError(LLBC_ERROR_CLIB); return ret; }