示例#1
0
void RwLock::EnterRead()
{
	LLOG("EnterRead");
	write_mutex.Enter();
	lock_mutex.Enter();
	readers++;
	lock_mutex.Leave();
	write_mutex.Leave();
	LLOG(".EnterRead");
}
示例#2
0
bool Thread::Run(Callback _cb)
{
	LLOG("Thread::Run");
	AtomicInc(sThreadCount);
	if(!threadr)
#ifndef CPU_BLACKFIN
		threadr = sMain = true;
#else
	{
		threadr = true;
		//the sMain replacement
#ifdef PLATFORM_POSIX
		pthread_t thid = pthread_self();
		vm.Enter();
		if(threadsv.Find(thid) < 0){
			//thread not yet present, mark present
			threadsv.Add(thid);
		}
		else
			RLOG("BUG: Multiple Add in Mt.cpp");
		vm.Leave();
#endif
	}
#endif
	Detach();
	Callback *cb = new Callback(_cb);
#ifdef PLATFORM_WIN32
	handle = (HANDLE)_beginthreadex(0, 0, sThreadRoutine, cb, 0, ((unsigned int *)(&thread_id)));
#endif
#ifdef PLATFORM_POSIX
	if(pthread_create(&handle, 0, sThreadRoutine, cb))
		handle = 0;
#endif
	return handle;
}
示例#3
0
void RwLock::LeaveWrite()
{
	LLOG("LeaveWrite");
	lock_mutex.Enter();
	lock_mutex.Leave();
	write_mutex.Leave();
	LLOG(".LeaveWrite");
}
示例#4
0
void RwLock::EnterWrite()
{
	LLOG("EnterWrite");
	write_mutex.Enter();
	LLOG("EnterWrite:write_mutex.Enter();");
	lock_mutex.Enter();
	ASSERT(!waiting_writer);
	waiting_writer = true;
	if(readers) {
		LLOG("EnterWrite:if(readers)");
		lock_mutex.Leave();
		writer_wait.Wait();
		lock_mutex.Enter();
		LLOG("EnterWrite:writer_wait.Wait();");
	}
	waiting_writer = false;
	lock_mutex.Leave();
	LLOG(".EnterWrite");
}
示例#5
0
void ProducerThread()
{
	for(int i = 0; i < N; i++) {
		if(i % 1000 == 0)
			LOG(i);
		mutex.Enter();
		queue.AddHead() = new int;
		mutex.Leave();
		todo.Release();
		MemoryCheckDebug();
	}
	LOG("Producer shutdown");
}
示例#6
0
void MutexTutorial()
{
	/// .`Mutex`
	
	/// Mutex ("mutual exclusion") is a well known concept in multithreaded programming: When
	/// multiple threads write and read the same data, the access has to be serialized using
	/// Mutex. Following invalid code demonstrates why:
	
	Thread t;
	
	int sum = 0;
	t.Run([&sum] {
		for(int i = 0; i < 1000000; i++)
			sum++;
	});
	
	for(int i = 0; i < 1000000; i++)
		sum++;
	
	t.Wait();
	DUMP(sum);
	
	/// While the expected value is 2000000, produced value is different. The problem is that
	/// both thread read / modify / write `sum` value without any locking. Using `Mutex` locks
	/// the `sum` and thus serializes access to it - read / modify / write sequence  is now
	/// exclusive for the thread that has `Mutex` locked, this fixing the issue. `Mutex` can be
	/// locked / unlocked with `Enter` / `Leave` methods. Alternatively, `Mutex::Lock` helper
	/// class locks `Mutex` in constructor and unlocks it in destructor:
	
	Mutex m;
	sum = 0;
	t.Run([&sum, &m] {
		for(int i = 0; i < 1000000; i++) {
			m.Enter();
			sum++;
			m.Leave();
		}
	});
	
	for(int i = 0; i < 1000000; i++) {
		Mutex::Lock __(m); // Lock m till the end of scope
		sum++;
	}
	
	t.Wait();
	DUMP(sum);
	
	///
}
示例#7
0
Thread::~Thread()
{
	Detach();
#ifdef CPU_BLACKFIN
#ifdef PLATFORM_POSIX
	//the static destruction replacement
	pthread_t thid = pthread_self();
	vm.Enter();
	int id = threadsv.Find(thid);
	if(id >= 0)
		threadsv.Remove(id);
	vm.Leave();
#endif
#endif
}
示例#8
0
void RwLock::LeaveRead()
{
	LLOG("LeaveRead");
	lock_mutex.Enter();
	LLOG("LeaveRead:lock_mutex.Enter();");
	if(--readers == 0 && waiting_writer) {
		LLOG("LeaveRead:if(--readers == 0 && writer)");
		ASSERT(readers == 0);
		writer_wait.Release();
		LLOG("LeaveRead:writer_wait.Release();");
	}
	LLOG("LeaveRead:--readers");
	lock_mutex.Leave();
	LLOG(".LeaveRead");
}
void RefObjects::BuryDeadites()
{
	if (_dead_list.Empty()) return;

	// Copy dead list
	DListForward dead_list;

	m_refobjects_lock.Enter();
	dead_list.Steal(_dead_list);
	m_refobjects_lock.Leave();

	for (iter ii = dead_list; ii; ++ii)
	{
		if (ii->OnFinalize())
			delete ii;
	}
}
示例#10
0
bool Thread::IsMain() //the calling thread is the Main Thread or the only one in App
{
#ifndef CPU_BLACKFIN
	return !threadr || sMain;
#else
	if(!threadr) 
		return true;
#ifdef PLATFORM_POSIX
	//the sMain replacement
	pthread_t thid = pthread_self();
	vm.Enter();
	if(threadsv.Find(thid) >= 0)
	{
		vm.Leave();
		return true;
	}
	vm.Leave();
#endif
	return false;
#endif
}
示例#11
0
AutoMutex::AutoMutex(Mutex &mutex)
{
    _mutex = &mutex;
    mutex.Enter();
}
示例#12
0
bool RefObjects::Entrypoint(void *param)
{
	CAT_INANE("RefObjects") << "Reaper starting...";

	while (!_shutdown_flag.Wait(513))
	{
		BuryDeadites();
	}

	CAT_INANE("RefObjects") << "Reaper caught shutdown signal, setting asynchronous shutdown flag...";

	m_refobjects_lock.Enter();

	_shutdown = true;

	// Now the shutdown flag is set everywhere synchronously.
	// The lists may only be modified from this function.

	m_refobjects_lock.Leave();

	CAT_INANE("RefObjects") << "Reaper destroying remaining active objects...";

	// For each remaining active object,
	for (iter ii = _active_list; ii; ++ii)
	{
		ii->Destroy(CAT_REFOBJECT_TRACE);
	}

	CAT_INANE("RefObjects") << "Reaper burying any easy dead...";

	BuryDeadites();

	CAT_INANE("RefObjects") << "Reaper spinning and finalizing the remaining active objects...";

	static const u32 HANG_THRESHOLD = 3000; // ms
	static const u32 SLEEP_TIME = 10; // ms
	u32 hang_counter = 0;

	// While active objects still exist,
	CAT_FOREVER
	{
		// Troll for zero reference counts
		for (iter ii = _active_list; ii; ++ii)
		{
			// If reference count hits zero,
			if (ii->_ref_count != 0) continue;

#if defined(CAT_TRACE_REFOBJECT)
			CAT_INANE("RefObjects") << ii->GetRefObjectName() << "#" << ii.GetRef() << " finalizing";
#endif

			_active_list.Erase(ii);

			// If object finalizing requests memory freed,
			if (ii->OnFinalize())
			{
#if defined(CAT_TRACE_REFOBJECT)
				CAT_INANE("RefObjects") << ii->GetRefObjectName() << "#" << ii.GetRef() << " freeing memory";
#endif

				delete ii;
			}

			// Reset hang counter
			hang_counter = 0;
		}

		// Quit when active list is empty
		if (_active_list.Empty()) break;

		// Find smallest ref count object
		iter smallest_obj = _active_list;
		u32 smallest_ref_count = smallest_obj->_ref_count;

		iter ii = _active_list;
		while (++ii)
		{
			if (ii->_ref_count < smallest_ref_count)
			{
				smallest_ref_count = ii->_ref_count;
				smallest_obj = ii;
			}
		}

		CAT_INANE("RefObjects") << smallest_obj->GetRefObjectName() << "#" << smallest_obj.GetRef() << " finalization delayed with " << smallest_ref_count << " dangling references (smallest found)";

		// If active list is not empty and hang count hasn't exceeded threshold,
		if (++hang_counter < HANG_THRESHOLD)
		{
			Clock::sleep(SLEEP_TIME);
			continue;
		}

		CAT_FATAL("RefObjects") << smallest_obj->GetRefObjectName() << "#" << smallest_obj.GetRef() << " finalization FORCED with " << smallest_ref_count << " dangling references (smallest found)";

		_active_list.Erase(smallest_obj);

		// If object finalizing requests memory freed,
		if (smallest_obj->OnFinalize())
		{
			CAT_FATAL("RefObjects") << smallest_obj->GetRefObjectName() << "#" << smallest_obj.GetRef() << " freeing memory for forced finalize";

			delete smallest_obj;
		}

		// Reset hang counter
		hang_counter = 0;
	}

	CAT_INANE("RefObjects") << "...Reaper going to sleep in a quiet field of dead objects";

	return true;
}