CDbapiConnMgr& CDbapiConnMgr::Instance(void) { static CSafeStaticPtr<CDbapiConnMgr> instance; return instance.Get(); }
const CCgiEntry& CCgiContext::GetRequestValue(const string& name, bool* is_found) const { pair<TCgiEntriesCI, TCgiEntriesCI> range = GetRequest().GetEntries().equal_range(name); if (range.second == range.first) { if ( is_found ) { *is_found = false; } static CSafeStaticPtr<CCgiEntry> s_EmptyCgiEntry; return s_EmptyCgiEntry.Get(); } if ( is_found ) { *is_found = true; } const CCgiEntry& value = range.first->second; while (++range.first != range.second) { if (range.first->second != value) { THROW1_TRACE(runtime_error, "duplicate entries in request with name: " + name + ": " + value.GetValue() + "!=" + range.first->second.GetValue()); } } return value; }
static const string& GetModuleName(const char* moduleName) { CFastMutexGuard GUARD(s_ModuleNameMutex); static CSafeStaticPtr< set<string> > s_ModuleNames; const string& s = *s_ModuleNames.Get().insert(moduleName).first; CClassTypeInfoBase::RegisterModule(s); return s; }
void CInterProcessLock::Unlock() { if (m_Handle == kInvalidLockHandle) { NCBI_THROW(CInterProcessLockException, eNotLocked, "Attempt to unlock not-yet-acquired lock"); } CFastMutexGuard LOCK(s_ProcessLock); // Check that lock with specified name not already locked // in the current process. TLocks::iterator it = s_Locks->find(m_SystemName); _VERIFY(it != s_Locks->end()); if ( it->second > 1 ) { // Just decrease reference counter it->second--; return; } // Release lock #if defined(NCBI_OS_UNIX) # if defined(F_TLOCK) int res = lockf(m_Handle, F_ULOCK, 0); # elif defined(F_SETLK) struct flock lockparam; lockparam.l_type = F_UNLCK; lockparam.l_whence = SEEK_SET; lockparam.l_start = 0; lockparam.l_len = 0; /* whole file */ int res = fcntl(m_Handle, F_SETLK, &lockparam); # else # error "No supported lock method. Please port this code." # endif if ( res < 0 ) { NCBI_THROW(CInterProcessLockException, eUnlockError, "Cannot release the lock"); } close(m_Handle); #elif defined(NCBI_OS_MSWIN) if ( !::ReleaseMutex(m_Handle) ) { NCBI_THROW(CInterProcessLockException, eUnlockError, "Cannot release the lock"); } ::CloseHandle(m_Handle); #endif m_Handle = kInvalidLockHandle; s_Locks->erase(m_SystemName); }
// CObject local new operator to mark allocation in heap void* CObject::operator new(size_t size) { _ASSERT(size >= sizeof(CObject)); size = max(size, sizeof(CObject) + sizeof(TCounter)); #ifdef USE_SINGLE_ALLOC void* ptr = single_alloc(size); sx_FillNewMemory(ptr, size); //static_cast<CObject*>(ptr)->m_Counter.Set(0); return ptr; #else void* ptr = ::operator new(size); #if USE_TLS_PTR // just remember pointer in TLS sx_PushLastNewPtr(ptr, eMagicCounterNew); #else// !USE_TLS_PTR #if USE_HEAPOBJ_LIST {{ CFastMutexGuard LOCK(sm_ObjectMutex); s_heap_obj->push_front(ptr); }} #else// !USE_HEAPOBJ_LIST sx_FillNewMemory(ptr, size); # if USE_COMPLEX_MASK GetSecondCounter(static_cast<CObject*>(ptr))->Set(eMagicCounterNew); # endif// USE_COMPLEX_MASK #endif// USE_HEAPOBJ_LIST static_cast<CObject*>(ptr)->m_Counter.Set(eMagicCounterNew); #endif// USE_TLS_PTR return ptr; #endif }
static SServerAddress* s_GetFallbackServer() { if (s_FallbackServer_Initialized) return s_FallbackServer->get(); try { string host, port; if (NStr::SplitInTwo(TCGI_NetCacheFallbackServer::GetDefault(), ":", host, port)) { s_FallbackServer->reset(new SServerAddress( g_NetService_gethostbyname(host), (unsigned short) NStr::StringToInt(port))); } } catch (...) { } s_FallbackServer_Initialized = true; return s_FallbackServer->get(); }
CValueConvert<SRunTimeSqlCP, CDB_Object>::operator const CTime&(void) const { CheckNULL(m_Value); CheckType(m_Value, eDB_SmallDateTime, eDB_DateTime); EDB_Type cur_type = m_Value.GetType(); if (cur_type == eDB_SmallDateTime) { return static_cast<const CDB_SmallDateTime&>(m_Value).Value(); } else if (cur_type == eDB_DateTime) { return static_cast<const CDB_DateTime&>(m_Value).Value(); } else { ReportTypeConvError(cur_type, "CTime"); } static CSafeStaticPtr<CTime> value; return value.Get(); }
// initialization in debug mode inline void CObject::InitCounter(void) { #if USE_TLS_PTR if ( CAtomicCounter::TValue type = sx_PopLastNewPtr(this) ) { switch ( type ) { case eMagicCounterNew: // allocated in heap m_Counter.Set(eInitCounterInHeap); break; case eMagicCounterPoolNew: // allocated in memory pool m_Counter.Set(eInitCounterInPool); break; default: ERR_POST_X(1, ObjFatal << "CObject::InitCounter: " "Bad s_LastNewType="<<type<< " at "<<StackTrace); // something is broken in TLS data // mark as not in heap m_Counter.Set(eInitCounterNotInHeap); break; } } else { // surely not in heap m_Counter.Set(eInitCounterNotInHeap); } #else // This code can't use Get(), which may block waiting for an // update that will never happen. // ATTENTION: this code can cause UMR (Uninit Mem Read) -- it's okay here! TCount main_counter = m_Counter.m_Value; if ( main_counter != eMagicCounterNew && main_counter != eMagicCounterPoolNew ) { // takes care of statically allocated case m_Counter.Set(eInitCounterNotInHeap); } else { bool inStack = false; #if USE_HEAPOBJ_LIST const void* ptr = dynamic_cast<const void*>(this); {{ CFastMutexGuard LOCK(sm_ObjectMutex); list<const void*>::iterator i = find( s_heap_obj->begin(), s_heap_obj->end(), ptr); inStack = (i == s_heap_obj->end()); if (!inStack) { s_heap_obj->erase(i); } }} #else // USE_HEAPOBJ_LIST # if USE_COMPLEX_MASK inStack = GetSecondCounter(this)->m_Value != main_counter; # endif // USE_COMPLEX_MASK // m_Counter == main_counter -> possibly in heap if ( !inStack ) { char stackObject; const char* stackObjectPtr = &stackObject; const char* objectPtr = reinterpret_cast<const char*>(this); # if defined STACK_GROWS_UP inStack = (objectPtr < stackObjectPtr) && (objectPtr > stackObjectPtr - STACK_THRESHOLD); # elif defined STACK_GROWS_DOWN inStack = (objectPtr > stackObjectPtr) && (objectPtr < stackObjectPtr + STACK_THRESHOLD); # else inStack = (objectPtr < stackObjectPtr + STACK_THRESHOLD) && (objectPtr > stackObjectPtr - STACK_THRESHOLD); # endif } #endif // USE_HEAPOBJ_LIST if ( inStack ) { // surely not in heap m_Counter.Set(eInitCounterInStack); } else if ( main_counter == eMagicCounterNew ) { // allocated in heap m_Counter.Set(eInitCounterInHeap); } else { // allocated in memory pool m_Counter.Set(eInitCounterInPool); } } #endif }
void CInterProcessLock::Lock(const CTimeout& timeout, const CTimeout& granularity) { CFastMutexGuard LOCK(s_ProcessLock); // Check that lock with specified name not already locked // in the current process. TLocks::iterator it = s_Locks->find(m_SystemName); if (m_Handle != kInvalidLockHandle) { // The lock is already set in this CInterProcessLock object, // just increase reference counter. _VERIFY(it != s_Locks->end()); it->second++; return; } else { if (it != s_Locks->end()) { // The lock already exists in the current process. // We can use one CInterProcessLock object with // multiple Lock() calls, but not with different // CInterProcessLock objects. For example, on MS-Windows, // we cannot wait on the same mutex in the same thread. // So, two different objects can set locks simultaneously. // And for OS-compatibility we can do nothing here, // except throwing an exception. NCBI_THROW(CInterProcessLockException, eMultipleLocks, "Attempt to lock already locked object " \ "in the same process"); } } // Try to acquire a lock with specified timeout #if defined(NCBI_OS_UNIX) // Open lock file mode_t perm = CDirEntry::MakeModeT( CDirEntry::fRead | CDirEntry::fWrite /* user */, CDirEntry::fRead | CDirEntry::fWrite /* group */, 0, 0 /* other & special */); int fd = open(m_SystemName.c_str(), O_CREAT | O_RDWR, perm); if (fd == -1) { NCBI_THROW(CInterProcessLockException, eCreateError, string("Error creating lockfile ") + m_SystemName + ": " + strerror(errno)); } // Try to acquire the lock int x_errno = 0; if (timeout.IsInfinite() || timeout.IsDefault()) { while ((x_errno = s_UnixLock(fd))) { if (errno != EAGAIN) break; } } else { unsigned long ms = timeout.GetAsMilliSeconds(); if ( !ms ) { // Timeout == 0 x_errno = s_UnixLock(fd); } else { // Timeout > 0 unsigned long ms_gran; if ( granularity.IsInfinite() || granularity.IsDefault() ) { ms_gran = min(ms/5, (unsigned long)500); } else { ms_gran = granularity.GetAsMilliSeconds(); } // Try to lock within specified timeout for (;;) { x_errno = s_UnixLock(fd); if ( !x_errno ) { // Successfully locked break; } if (x_errno != EACCES && x_errno != EAGAIN ) { // Error break; } // Otherwise -- sleep granularity timeout unsigned long ms_sleep = ms_gran; if (ms_sleep > ms) { ms_sleep = ms; } if ( !ms_sleep ) { break; } SleepMilliSec(ms_sleep); ms -= ms_sleep; } // Timeout if ( !ms ) { close(fd); NCBI_THROW(CInterProcessLockException, eLockTimeout, "The lock could not be acquired in the time " \ "allotted"); } } // if (!ms) } // if (timeout.IsInfinite()) // Error if ( x_errno ) { close(fd); NCBI_THROW(CInterProcessLockException, eLockError, "Error creating lock"); } // Success m_Handle = fd; #elif defined(NCBI_OS_MSWIN) HANDLE handle = ::CreateMutex(NULL, TRUE, _T_XCSTRING(m_SystemName)); errno_t errcode = ::GetLastError(); if (handle == kInvalidLockHandle) { switch(errcode) { case ERROR_ACCESS_DENIED: // Mutex with specified name already exists, // but we don't have enough rights to open it. NCBI_THROW(CInterProcessLockException, eLockError, "The lock already exists"); break; case ERROR_INVALID_HANDLE: // Some system object with the same name already exists NCBI_THROW(CInterProcessLockException, eLockError, "Error creating lock, system object with the same" \ "name already exists"); break; default: // Unknown error NCBI_THROW(CInterProcessLockException, eCreateError, "Error creating lock"); break; } } else { // Mutex with specified name already exists if (errcode == ERROR_ALREADY_EXISTS) { // Wait DWORD res; if (timeout.IsInfinite() || timeout.IsDefault()) { res = WaitForSingleObject(handle, INFINITE); } else { res = WaitForSingleObject(handle, timeout.GetAsMilliSeconds()); } switch(res) { case WAIT_OBJECT_0: // The lock has been acquired break; case WAIT_TIMEOUT: ::CloseHandle(handle); NCBI_THROW(CInterProcessLockException, eLockTimeout, "The lock could not be acquired in the time " \ "allotted"); break; case WAIT_ABANDONED: // The lock is in abandoned state... Other thread/process // owning it was terminated. We can reuse this mutex, but // it is better to wait until it will be released by OS. /* FALLTHRU */ default: ::CloseHandle(handle); NCBI_THROW(CInterProcessLockException, eLockError, "Error creating lock"); break; } } m_Handle = handle; } #endif // Set reference counter to 1 (*s_Locks)[m_SystemName] = 1; }