Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
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;
	}

}