UInt32 UTF8toUCS4(const char* utf8char) { BLOCXX_ASSERT(utf8char != 0); BLOCXX_ASSERT(utf8char[0] != '\0'); const char* p = utf8char; const UInt32 c0 = static_cast<UInt8>(p[0]); const UInt32 bad = 0xFFFFFFFF; switch (SequenceLengthTable[c0]) { case 1: { return c0; } case 2: { // check for short (invalid) utf8 sequence if (p[1] == '\0') { return bad; } const UInt32 c1 = static_cast<UInt8>(p[1]); return ((c0 & 0x1fu) << 6) | (c1 & 0x3fu); } case 3: { // check for short (invalid) utf8 sequence if (p[1] == '\0' || p[2] == '\0') { return bad; } const UInt32 c1 = static_cast<UInt8>(p[1]); const UInt32 c2 = static_cast<UInt8>(p[2]); return ((c0 & 0x0fu) << 12) | ((c1 & 0x3fu) << 6) | (c2 & 0x3fu); } case 4: { // check for short (invalid) utf8 sequence if (p[1] == '\0' || p[2] == '\0' || p[3] == '\0') { return bad; } const UInt32 c1 = static_cast<UInt8>(p[1]); const UInt32 c2 = static_cast<UInt8>(p[2]); const UInt32 c3 = static_cast<UInt8>(p[3]); return ((c0 & 0x03u) << 18) | ((c1 & 0x3fu) << 12) | ((c2 & 0x3fu) << 6) | (c3 & 0x3fu); } default: { // invalid, just skip it break; } } return bad; }
String::String(ETakeOwnershipFlag, char* allocatedMemory, size_t len) : m_buf(NULL) { BLOCXX_ASSERT(allocatedMemory != 0); AutoPtrVec<char> p(allocatedMemory); m_buf = new ByteBuf(p, len); }
void GenericRWLockImpl<IdT, CompareT>::acquireReadLock(const IdT id, const Timeout& timeout) { TimeoutTimer timer(timeout); NonRecursiveMutexLock l(m_guard); typename IdMap::iterator info = m_lockerInfo.find(id); if (info != m_lockerInfo.end()) { LockerInfo& ti(info->second); // id already have a read or write lock, so just increment. BLOCXX_ASSERT(ti.isReader() || ti.isWriter()); ++ti.readCount; return; } // id is a new reader while (!m_canRead || m_numWriters > 0) { if (!m_waiting_readers.timedWait(l, timer.asAbsoluteTimeout())) { BLOCXX_THROW(TimeoutException, "Timeout while waiting for read lock."); } } // Increase the reader count LockerInfo lockerInfo; lockerInfo.readCount = 1; lockerInfo.writeCount = 0; m_lockerInfo.insert(typename IdMap::value_type(id, lockerInfo)); ++m_numReaders; }
char& String::operator[] (size_t ndx) { #ifdef BLOCXX_DEBUG BLOCXX_ASSERT(ndx <= length()); #endif if (!m_buf) // then length() == 0 { // Only needed in case ndx == 0, but doesn't hurt if ndx > 0 m_buf = new ByteBuf(""); } return (ndx <= m_buf->length() ? m_buf->data()[ndx] : nullChar); }
const char& String::operator[] (size_t ndx) const { #ifdef BLOCXX_DEBUG BLOCXX_ASSERT(ndx <= length()); #endif if (!m_buf) // then length() == 0 { // Only needed in case ndx == 0, but doesn't hurt if ndx > 0 const_cast<buf_t &>(m_buf) = new ByteBuf(""); } return *(ndx <= m_buf->length() ? m_buf->data() + ndx : &cnullChar); }
void GenericRWLockImpl<IdT, CompareT>::releaseWriteLock(const IdT id) { NonRecursiveMutexLock l(m_guard); typename IdMap::iterator pInfo = m_lockerInfo.find(id); if (pInfo == m_lockerInfo.end() || !pInfo->second.isWriter()) { BLOCXX_THROW(GenericRWLockImplException, "Cannot release a write lock when no write lock is held"); } LockerInfo& ti(pInfo->second); BLOCXX_ASSERT(ti.isWriter()); --ti.writeCount; if (!ti.isWriter()) { --m_numWriters; BLOCXX_ASSERT(m_numWriters == 0); m_canRead = true; if (ti.isReader()) { // restore reader status ++m_numReaders; } else { // This id no longer holds locks. m_waiting_writers.notifyOne(); m_lockerInfo.erase(pInfo); } m_waiting_readers.notifyAll(); } }
void GenericRWLockImpl<IdT, CompareT>::acquireWriteLock(const IdT id, const Timeout& timeout) { // 7 cases: // 1. No id has the lock // Get the lock // 2. This id has the write lock // Increment the lock count // 3. Another id has the write lock & other ids may be waiting for read and/or write locks. // Block until the lock is acquired. // 4. Only this id has a read lock // Increment the write lock count . // 5. >0 other ids have the read lock & other ids may be waiting for write locks. // Block until the write lock is acquired. // 6. This id and other ids have the read lock // Block new readers and writers and wait until existing readers finish. // 7. This id and other ids have the read lock and one of the other ids has requested a write lock. // Throw an exception. TimeoutTimer timer(timeout); NonRecursiveMutexLock l(m_guard); typename IdMap::iterator pInfo = m_lockerInfo.find(id); if (pInfo != m_lockerInfo.end()) { // This id already has some sort of lock LockerInfo& ti(pInfo->second); BLOCXX_ASSERT(ti.isReader() || ti.isWriter()); if (!ti.isWriter()) { // The id is upgrading BLOCXX_ASSERT(m_numWriters == 0 || m_numWriters == 1); if (m_numWriters == 1) { // another id beat us to upgrading the write lock. Throw an exception. BLOCXX_THROW(DeadlockException, "Upgrading read lock to a write lock failed, another upgrade is already in progress."); } // switch from being a reader to a writer --m_numReaders; // mark us as a writer, this will prevent other ids from becoming a writer ++m_numWriters; // This thread isn't the only reader. Wait for others to finish. while (m_numReaders != 0) { // stop new readers - inside while loop, because it may get reset by other ids releasing locks. m_canRead = false; if (!m_waiting_writers.timedWait(l, timer.asAbsoluteTimeout())) { // undo changes ++m_numReaders; --m_numWriters; m_canRead = true; if (m_numWriters == 0) { m_waiting_readers.notifyAll(); } BLOCXX_THROW(TimeoutException, "Timeout while waiting for write lock."); } } } ++ti.writeCount; } else { // This id doesn't have any lock while (m_numReaders != 0 || m_numWriters != 0) { // stop new readers m_canRead = false; if (!m_waiting_writers.timedWait(l, timer.asAbsoluteTimeout())) { m_canRead = true; if (m_numWriters == 0) { m_waiting_readers.notifyAll(); } BLOCXX_THROW(TimeoutException, "Timeout while waiting for write lock."); } } LockerInfo ti; ti.readCount = 0; ti.writeCount = 1; m_lockerInfo.insert(typename IdMap::value_type(id, ti)); ++m_numWriters; m_canRead = false; } }