haiku/src/system/kernel/TeamThreadTables.h
Ingo Weinhold 24df65921b Merged signals-merge branch into trunk with the following changes:
* Reorganized the kernel locking related to threads and teams.
* We now discriminate correctly between process and thread signals. Signal
  handlers have been moved to teams. Fixes #5679.
* Implemented real-time signal support, including signal queuing, SA_SIGINFO
  support, sigqueue(), sigwaitinfo(), sigtimedwait(), waitid(), and the addition
  of the real-time signal range. Closes #1935 and #2695.
* Gave SIGBUS a separate signal number. Fixes #6704.
* Implemented <time.h> clock and timer support, and fixed/completed alarm() and
  [set]itimer(). Closes #5682.
* Implemented support for thread cancellation. Closes #5686.
* Moved send_signal() from <signal.h> to <OS.h>. Fixes #7554.
* Lots over smaller more or less related changes.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42116 a95241bf-73f2-0310-859d-f6bbb57e9c96
2011-06-12 00:00:23 +00:00

185 lines
3.2 KiB
C++

/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_TEAM_THREAD_TABLES_H
#define KERNEL_TEAM_THREAD_TABLES_H
#include <thread_types.h>
namespace BKernel {
template<typename Element>
struct TeamThreadTable {
public:
typedef typename Element::id_type id_type;
typedef typename Element::iterator_type IteratorEntry;
struct Iterator {
Iterator()
:
fNext(NULL)
{
}
Iterator(IteratorEntry* nextEntry)
{
_SetNext(nextEntry);
}
bool HasNext() const
{
return fNext != NULL;
}
Element* Next()
{
Element* result = fNext;
if (result != NULL)
_SetNext(result->GetDoublyLinkedListLink()->next);
return result;
}
private:
void _SetNext(IteratorEntry* entry)
{
while (entry != NULL) {
if (entry->id >= 0) {
fNext = static_cast<Element*>(entry);
return;
}
entry = entry->GetDoublyLinkedListLink()->next;
}
fNext = NULL;
}
private:
Element* fNext;
};
public:
TeamThreadTable()
:
fNextSerialNumber(1)
{
}
status_t Init(size_t initialSize)
{
return fTable.Init(initialSize);
}
void Insert(Element* element)
{
element->serial_number = fNextSerialNumber++;
fTable.InsertUnchecked(element);
fList.Add(element);
}
void Remove(Element* element)
{
fTable.RemoveUnchecked(element);
fList.Remove(element);
}
Element* Lookup(id_type id, bool visibleOnly = true) const
{
Element* element = fTable.Lookup(id);
return element != NULL && (!visibleOnly || element->visible)
? element : NULL;
}
/*! Gets an iterator.
The iterator iterates through all, including invisible, entries!
*/
Iterator GetIterator()
{
return Iterator(fList.Head());
}
void InsertIteratorEntry(IteratorEntry* entry)
{
// add to front
entry->id = -1;
entry->visible = false;
fList.Add(entry, false);
}
void RemoveIteratorEntry(IteratorEntry* entry)
{
fList.Remove(entry);
}
Element* NextElement(IteratorEntry* entry, bool visibleOnly = true)
{
if (entry == fList.Tail())
return NULL;
IteratorEntry* nextEntry = entry;
while (true) {
nextEntry = nextEntry->GetDoublyLinkedListLink()->next;
if (nextEntry == NULL) {
// end of list -- requeue entry at the end and return NULL
fList.Remove(entry);
fList.Add(entry);
return NULL;
}
if (nextEntry->id >= 0 && (!visibleOnly || nextEntry->visible)) {
// found an element -- requeue entry after element
Element* element = static_cast<Element*>(nextEntry);
fList.Remove(entry);
fList.InsertAfter(nextEntry, entry);
return element;
}
}
}
private:
struct HashDefinition {
typedef id_type KeyType;
typedef Element ValueType;
size_t HashKey(id_type key) const
{
return key;
}
size_t Hash(Element* value) const
{
return HashKey(value->id);
}
bool Compare(id_type key, Element* value) const
{
return value->id == key;
}
Element*& GetLink(Element* value) const
{
return value->hash_next;
}
};
typedef BOpenHashTable<HashDefinition> ElementTable;
typedef DoublyLinkedList<IteratorEntry> List;
private:
ElementTable fTable;
List fList;
int64 fNextSerialNumber;
};
} // namespace BKernel
#endif // KERNEL_TEAM_THREAD_TABLES_H