Merge branch 'scheduler'
Conflicts: build/jam/packages/Haiku headers/os/kernel/OS.h headers/os/opengl/GLRenderer.h headers/private/shared/cpu_type.h src/add-ons/kernel/drivers/power/acpi_battery/acpi_battery.h src/bin/sysinfo.cpp src/bin/top.c src/system/kernel/arch/x86/arch_system_info.cpp src/system/kernel/port.cpp
This commit is contained in:
@@ -160,6 +160,144 @@ private:
|
||||
typedef AutoLocker<spinlock, InterruptsSpinLocking> InterruptsSpinLocker;
|
||||
|
||||
|
||||
class ReadSpinLocking {
|
||||
public:
|
||||
inline bool Lock(rw_spinlock* lockable)
|
||||
{
|
||||
acquire_read_spinlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(rw_spinlock* lockable)
|
||||
{
|
||||
release_read_spinlock(lockable);
|
||||
}
|
||||
};
|
||||
|
||||
typedef AutoLocker<rw_spinlock, ReadSpinLocking> ReadSpinLocker;
|
||||
|
||||
|
||||
class InterruptsReadSpinLocking {
|
||||
public:
|
||||
InterruptsReadSpinLocking()
|
||||
:
|
||||
fState(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Lock(rw_spinlock* lockable)
|
||||
{
|
||||
fState = disable_interrupts();
|
||||
acquire_read_spinlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(rw_spinlock* lockable)
|
||||
{
|
||||
release_read_spinlock(lockable);
|
||||
restore_interrupts(fState);
|
||||
}
|
||||
|
||||
private:
|
||||
int fState;
|
||||
};
|
||||
|
||||
typedef AutoLocker<rw_spinlock, InterruptsReadSpinLocking>
|
||||
InterruptsReadSpinLocker;
|
||||
|
||||
|
||||
class WriteSpinLocking {
|
||||
public:
|
||||
inline bool Lock(rw_spinlock* lockable)
|
||||
{
|
||||
acquire_write_spinlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(rw_spinlock* lockable)
|
||||
{
|
||||
release_write_spinlock(lockable);
|
||||
}
|
||||
};
|
||||
|
||||
typedef AutoLocker<rw_spinlock, WriteSpinLocking> WriteSpinLocker;
|
||||
|
||||
|
||||
class InterruptsWriteSpinLocking {
|
||||
public:
|
||||
InterruptsWriteSpinLocking()
|
||||
:
|
||||
fState(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Lock(rw_spinlock* lockable)
|
||||
{
|
||||
fState = disable_interrupts();
|
||||
acquire_write_spinlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(rw_spinlock* lockable)
|
||||
{
|
||||
release_write_spinlock(lockable);
|
||||
restore_interrupts(fState);
|
||||
}
|
||||
|
||||
private:
|
||||
int fState;
|
||||
};
|
||||
|
||||
typedef AutoLocker<rw_spinlock, InterruptsWriteSpinLocking>
|
||||
InterruptsWriteSpinLocker;
|
||||
|
||||
|
||||
class WriteSequentialLocking {
|
||||
public:
|
||||
inline bool Lock(seqlock* lockable)
|
||||
{
|
||||
acquire_write_seqlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(seqlock* lockable)
|
||||
{
|
||||
release_write_seqlock(lockable);
|
||||
}
|
||||
};
|
||||
|
||||
typedef AutoLocker<seqlock, WriteSequentialLocking> WriteSequentialLocker;
|
||||
|
||||
|
||||
class InterruptsWriteSequentialLocking {
|
||||
public:
|
||||
InterruptsWriteSequentialLocking()
|
||||
:
|
||||
fState(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool Lock(seqlock* lockable)
|
||||
{
|
||||
fState = disable_interrupts();
|
||||
acquire_write_seqlock(lockable);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Unlock(seqlock* lockable)
|
||||
{
|
||||
release_write_seqlock(lockable);
|
||||
restore_interrupts(fState);
|
||||
}
|
||||
|
||||
private:
|
||||
int fState;
|
||||
};
|
||||
|
||||
typedef AutoLocker<seqlock, InterruptsWriteSequentialLocking>
|
||||
InterruptsWriteSequentialLocker;
|
||||
|
||||
|
||||
class ThreadCPUPinLocking {
|
||||
public:
|
||||
inline bool Lock(Thread* thread)
|
||||
@@ -191,6 +329,12 @@ using BPrivate::WriteLocker;
|
||||
using BPrivate::InterruptsLocker;
|
||||
using BPrivate::SpinLocker;
|
||||
using BPrivate::InterruptsSpinLocker;
|
||||
using BPrivate::ReadSpinLocker;
|
||||
using BPrivate::InterruptsReadSpinLocker;
|
||||
using BPrivate::WriteSpinLocker;
|
||||
using BPrivate::InterruptsWriteSpinLocker;
|
||||
using BPrivate::WriteSequentialLocker;
|
||||
using BPrivate::InterruptsWriteSequentialLocker;
|
||||
using BPrivate::ThreadCPUPinner;
|
||||
using BPrivate::TeamLocker;
|
||||
using BPrivate::ThreadLocker;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2013 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_BITUTIL_H
|
||||
#define KERNEL_UTIL_BITUTIL_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
static inline uint32
|
||||
next_power_of_2(uint32 v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html
|
||||
static inline uint32
|
||||
count_set_bits(uint32 v)
|
||||
{
|
||||
v = v - ((v >> 1) & 0x55555555);
|
||||
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
|
||||
return (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32
|
||||
log2(uint32 v)
|
||||
{
|
||||
static const int MultiplyDeBruijnBitPosition[32] = {
|
||||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30,
|
||||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31
|
||||
};
|
||||
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
|
||||
return MultiplyDeBruijnBitPosition[(uint32)(v * 0x07C4ACDDU) >> 27];
|
||||
}
|
||||
|
||||
|
||||
#endif // KERNEL_UTIL_RANDOM_H
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2013 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_BITMAP_H
|
||||
#define KERNEL_UTIL_BITMAP_H
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class Bitmap {
|
||||
public:
|
||||
Bitmap(int bitCount);
|
||||
~Bitmap();
|
||||
|
||||
inline status_t GetInitStatus();
|
||||
|
||||
inline bool Get(int index) const;
|
||||
inline void Set(int index);
|
||||
inline void Clear(int index);
|
||||
|
||||
int GetHighestSet() const;
|
||||
|
||||
private:
|
||||
status_t fInitStatus;
|
||||
|
||||
int fElementsCount;
|
||||
int fSize;
|
||||
addr_t* fBits;
|
||||
|
||||
static const int kBitsPerElement;
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
Bitmap::GetInitStatus()
|
||||
{
|
||||
return fInitStatus;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Bitmap::Get(int index) const
|
||||
{
|
||||
ASSERT(index < fSize);
|
||||
|
||||
const int kArrayElement = index / kBitsPerElement;
|
||||
const addr_t kBitMask = addr_t(1) << (index % kBitsPerElement);
|
||||
return fBits[kArrayElement] & kBitMask;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Bitmap::Set(int index)
|
||||
{
|
||||
ASSERT(index < fSize);
|
||||
|
||||
const int kArrayElement = index / kBitsPerElement;
|
||||
const addr_t kBitMask = addr_t(1) << (index % kBitsPerElement);
|
||||
fBits[kArrayElement] |= kBitMask;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Bitmap::Clear(int index)
|
||||
{
|
||||
ASSERT(index < fSize);
|
||||
|
||||
const int kArrayElement = index / kBitsPerElement;
|
||||
const addr_t kBitMask = addr_t(1) << (index % kBitsPerElement);
|
||||
fBits[kArrayElement] &= ~addr_t(kBitMask);
|
||||
}
|
||||
|
||||
|
||||
#endif // KERNEL_UTIL_BITMAP_H
|
||||
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright 2013 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_HEAP_H
|
||||
#define KERNEL_UTIL_HEAP_H
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
struct HeapLink {
|
||||
HeapLink();
|
||||
|
||||
int fIndex;
|
||||
Key fKey;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key>
|
||||
class HeapLinkImpl {
|
||||
private:
|
||||
typedef HeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* GetHeapLink();
|
||||
|
||||
private:
|
||||
Link fHeapLink;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key>
|
||||
class HeapStandardGetLink {
|
||||
private:
|
||||
typedef HeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* operator()(Element* element) const;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key,
|
||||
HeapLink<Element, Key> Element::*LinkMember>
|
||||
class HeapMemberGetLink {
|
||||
private:
|
||||
typedef HeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* operator()(Element* element) const;
|
||||
};
|
||||
|
||||
template<typename Key>
|
||||
class HeapLesserCompare {
|
||||
public:
|
||||
inline bool operator()(Key a, Key b);
|
||||
};
|
||||
|
||||
template<typename Key>
|
||||
class HeapGreaterCompare {
|
||||
public:
|
||||
inline bool operator()(Key a, Key b);
|
||||
};
|
||||
|
||||
#define HEAP_TEMPLATE_LIST \
|
||||
template<typename Element, typename Key, typename Compare, typename GetLink>
|
||||
#define HEAP_CLASS_NAME Heap<Element, Key, Compare, GetLink>
|
||||
|
||||
template<typename Element, typename Key,
|
||||
typename Compare = HeapLesserCompare<Key>,
|
||||
typename GetLink = HeapStandardGetLink<Element, Key> >
|
||||
class Heap {
|
||||
public:
|
||||
Heap();
|
||||
Heap(int initialSize);
|
||||
~Heap();
|
||||
|
||||
inline Element* PeekRoot() const;
|
||||
|
||||
static const Key& GetKey(Element* element);
|
||||
|
||||
inline void ModifyKey(Element* element, Key newKey);
|
||||
|
||||
inline void RemoveRoot();
|
||||
inline status_t Insert(Element* element, Key key);
|
||||
|
||||
private:
|
||||
status_t _GrowHeap(int minimalSize = 0);
|
||||
|
||||
void _MoveUp(HeapLink<Element, Key>* link);
|
||||
void _MoveDown(HeapLink<Element, Key>* link);
|
||||
|
||||
Element** fElements;
|
||||
int fLastElement;
|
||||
int fSize;
|
||||
|
||||
static Compare sCompare;
|
||||
static GetLink sGetLink;
|
||||
};
|
||||
|
||||
|
||||
#if KDEBUG
|
||||
template<typename Element, typename Key>
|
||||
HeapLink<Element, Key>::HeapLink()
|
||||
:
|
||||
fIndex(-1)
|
||||
{
|
||||
}
|
||||
#else
|
||||
template<typename Element, typename Key>
|
||||
HeapLink<Element, Key>::HeapLink()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
HeapLink<Element, Key>*
|
||||
HeapLinkImpl<Element, Key>::GetHeapLink()
|
||||
{
|
||||
return &fHeapLink;
|
||||
}
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
HeapLink<Element, Key>*
|
||||
HeapStandardGetLink<Element, Key>::operator()(Element* element) const
|
||||
{
|
||||
return element->GetHeapLink();
|
||||
}
|
||||
|
||||
|
||||
template<typename Element, typename Key,
|
||||
HeapLink<Element, Key> Element::*LinkMember>
|
||||
HeapLink<Element, Key>*
|
||||
HeapMemberGetLink<Element, Key, LinkMember>::operator()(Element* element) const
|
||||
{
|
||||
return &(element->*LinkMember);
|
||||
}
|
||||
|
||||
|
||||
template<typename Key>
|
||||
bool
|
||||
HeapLesserCompare<Key>::operator()(Key a, Key b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
|
||||
template<typename Key>
|
||||
bool
|
||||
HeapGreaterCompare<Key>::operator()(Key a, Key b)
|
||||
{
|
||||
return a > b;
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
HEAP_CLASS_NAME::Heap()
|
||||
:
|
||||
fElements(NULL),
|
||||
fLastElement(0),
|
||||
fSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
HEAP_CLASS_NAME::Heap(int initialSize)
|
||||
:
|
||||
fElements(NULL),
|
||||
fLastElement(0),
|
||||
fSize(0)
|
||||
{
|
||||
_GrowHeap(initialSize);
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
HEAP_CLASS_NAME::~Heap()
|
||||
{
|
||||
free(fElements);
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
Element*
|
||||
HEAP_CLASS_NAME::PeekRoot() const
|
||||
{
|
||||
if (fLastElement > 0)
|
||||
return fElements[0];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
const Key&
|
||||
HEAP_CLASS_NAME::GetKey(Element* element)
|
||||
{
|
||||
return sGetLink(element)->fKey;
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
void
|
||||
HEAP_CLASS_NAME::ModifyKey(Element* element, Key newKey)
|
||||
{
|
||||
HeapLink<Element, Key>* link = sGetLink(element);
|
||||
|
||||
ASSERT(link->fIndex >= 0 && link->fIndex < fLastElement);
|
||||
Key oldKey = link->fKey;
|
||||
link->fKey = newKey;
|
||||
|
||||
if (sCompare(newKey, oldKey))
|
||||
_MoveUp(link);
|
||||
else if (sCompare(oldKey, newKey))
|
||||
_MoveDown(link);
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
void
|
||||
HEAP_CLASS_NAME::RemoveRoot()
|
||||
{
|
||||
ASSERT(fLastElement > 0);
|
||||
|
||||
#if KDEBUG
|
||||
Element* element = PeekRoot();
|
||||
HeapLink<Element, Key>* link = sGetLink(element);
|
||||
ASSERT(link->fIndex != -1);
|
||||
link->fIndex = -1;
|
||||
#endif
|
||||
|
||||
fLastElement--;
|
||||
if (fLastElement > 0) {
|
||||
Element* lastElement = fElements[fLastElement];
|
||||
fElements[0] = lastElement;
|
||||
sGetLink(lastElement)->fIndex = 0;
|
||||
_MoveDown(sGetLink(lastElement));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
status_t
|
||||
HEAP_CLASS_NAME::Insert(Element* element, Key key)
|
||||
{
|
||||
if (fLastElement == fSize) {
|
||||
status_t result = _GrowHeap();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
ASSERT(fLastElement != fSize);
|
||||
|
||||
HeapLink<Element, Key>* link = sGetLink(element);
|
||||
|
||||
ASSERT(link->fIndex == -1);
|
||||
|
||||
fElements[fLastElement] = element;
|
||||
link->fIndex = fLastElement++;
|
||||
link->fKey = key;
|
||||
_MoveUp(link);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
status_t
|
||||
HEAP_CLASS_NAME::_GrowHeap(int minimalSize)
|
||||
{
|
||||
int newSize = max_c(max_c(fSize * 2, 4), minimalSize);
|
||||
|
||||
size_t arraySize = newSize * sizeof(Element*);
|
||||
Element** newBuffer
|
||||
= reinterpret_cast<Element**>(realloc(fElements, arraySize));
|
||||
if (newBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fElements = newBuffer;
|
||||
fSize = newSize;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
void
|
||||
HEAP_CLASS_NAME::_MoveUp(HeapLink<Element, Key>* link)
|
||||
{
|
||||
while (true) {
|
||||
int parent = (link->fIndex - 1) / 2;
|
||||
if (link->fIndex > 0
|
||||
&& sCompare(link->fKey, sGetLink(fElements[parent])->fKey)) {
|
||||
|
||||
sGetLink(fElements[parent])->fIndex = link->fIndex;
|
||||
|
||||
Element* element = fElements[link->fIndex];
|
||||
fElements[link->fIndex] = fElements[parent];
|
||||
fElements[parent] = element;
|
||||
|
||||
link->fIndex = parent;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
void
|
||||
HEAP_CLASS_NAME::_MoveDown(HeapLink<Element, Key>* link)
|
||||
{
|
||||
int current;
|
||||
|
||||
while (true) {
|
||||
current = link->fIndex;
|
||||
|
||||
int child = 2 * link->fIndex + 1;
|
||||
if (child < fLastElement
|
||||
&& sCompare(sGetLink(fElements[child])->fKey, link->fKey)) {
|
||||
current = child;
|
||||
}
|
||||
|
||||
child = 2 * link->fIndex + 2;
|
||||
if (child < fLastElement
|
||||
&& sCompare(sGetLink(fElements[child])->fKey,
|
||||
sGetLink(fElements[current])->fKey)) {
|
||||
current = child;
|
||||
}
|
||||
|
||||
if (link->fIndex == current)
|
||||
break;
|
||||
|
||||
sGetLink(fElements[current])->fIndex = link->fIndex;
|
||||
|
||||
Element* element = fElements[link->fIndex];
|
||||
fElements[link->fIndex] = fElements[current];
|
||||
fElements[current] = element;
|
||||
|
||||
link->fIndex = current;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
Compare HEAP_CLASS_NAME::sCompare;
|
||||
|
||||
HEAP_TEMPLATE_LIST
|
||||
GetLink HEAP_CLASS_NAME::sGetLink;
|
||||
|
||||
|
||||
#endif // KERNEL_UTIL_HEAP_H
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
* Copyright 2013 Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Paweł Dziepak, [email protected]
|
||||
*/
|
||||
#ifndef KERNEL_UTIL_MIN_MAX_HEAP_H
|
||||
#define KERNEL_UTIL_MIN_MAX_HEAP_H
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
struct MinMaxHeapLink {
|
||||
MinMaxHeapLink();
|
||||
|
||||
bool fMinTree;
|
||||
int fIndex;
|
||||
Key fKey;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key>
|
||||
class MinMaxHeapLinkImpl {
|
||||
private:
|
||||
typedef MinMaxHeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* GetMinMaxHeapLink();
|
||||
|
||||
private:
|
||||
Link fMinMaxHeapLink;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key>
|
||||
class MinMaxHeapStandardGetLink {
|
||||
private:
|
||||
typedef MinMaxHeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* operator()(Element* element) const;
|
||||
};
|
||||
|
||||
template<typename Element, typename Key,
|
||||
MinMaxHeapLink<Element, Key> Element::*LinkMember>
|
||||
class MinMaxHeapMemberGetLink {
|
||||
private:
|
||||
typedef MinMaxHeapLink<Element, Key> Link;
|
||||
|
||||
public:
|
||||
inline Link* operator()(Element* element) const;
|
||||
};
|
||||
|
||||
template<typename Key>
|
||||
class MinMaxHeapCompare {
|
||||
public:
|
||||
inline bool operator()(Key a, Key b);
|
||||
};
|
||||
|
||||
#define MIN_MAX_HEAP_TEMPLATE_LIST \
|
||||
template<typename Element, typename Key, typename Compare, typename GetLink>
|
||||
#define MIN_MAX_HEAP_CLASS_NAME MinMaxHeap<Element, Key, Compare, GetLink>
|
||||
|
||||
template<typename Element, typename Key,
|
||||
typename Compare = MinMaxHeapCompare<Key>,
|
||||
typename GetLink = MinMaxHeapStandardGetLink<Element, Key> >
|
||||
class MinMaxHeap {
|
||||
public:
|
||||
MinMaxHeap();
|
||||
MinMaxHeap(int initialSize);
|
||||
~MinMaxHeap();
|
||||
|
||||
inline Element* PeekMinimum() const;
|
||||
inline Element* PeekMaximum() const;
|
||||
|
||||
static const Key& GetKey(Element* element);
|
||||
|
||||
inline void ModifyKey(Element* element, Key newKey);
|
||||
|
||||
inline void RemoveMinimum();
|
||||
inline void RemoveMaximum();
|
||||
|
||||
inline status_t Insert(Element* element, Key key);
|
||||
|
||||
private:
|
||||
status_t _GrowHeap(int minimalSize = 0);
|
||||
|
||||
void _MoveUp(MinMaxHeapLink<Element, Key>* link);
|
||||
void _MoveDown(MinMaxHeapLink<Element, Key>* link);
|
||||
bool _ChangeTree(MinMaxHeapLink<Element, Key>* link);
|
||||
|
||||
void _RemoveLast(bool minTree);
|
||||
|
||||
Element** fMinElements;
|
||||
int fMinLastElement;
|
||||
|
||||
Element** fMaxElements;
|
||||
int fMaxLastElement;
|
||||
|
||||
int fSize;
|
||||
|
||||
static Compare sCompare;
|
||||
static GetLink sGetLink;
|
||||
};
|
||||
|
||||
|
||||
#if KDEBUG
|
||||
template<typename Element, typename Key>
|
||||
MinMaxHeapLink<Element, Key>::MinMaxHeapLink()
|
||||
:
|
||||
fIndex(-1)
|
||||
{
|
||||
}
|
||||
#else
|
||||
template<typename Element, typename Key>
|
||||
MinMaxHeapLink<Element, Key>::MinMaxHeapLink()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
MinMaxHeapLink<Element, Key>*
|
||||
MinMaxHeapLinkImpl<Element, Key>::GetMinMaxHeapLink()
|
||||
{
|
||||
return &fMinMaxHeapLink;
|
||||
}
|
||||
|
||||
|
||||
template<typename Element, typename Key>
|
||||
MinMaxHeapLink<Element, Key>*
|
||||
MinMaxHeapStandardGetLink<Element, Key>::operator()(Element* element) const
|
||||
{
|
||||
return element->GetMinMaxHeapLink();
|
||||
}
|
||||
|
||||
|
||||
template<typename Element, typename Key,
|
||||
MinMaxHeapLink<Element, Key> Element::*LinkMember>
|
||||
MinMaxHeapLink<Element, Key>*
|
||||
MinMaxHeapMemberGetLink<Element, Key, LinkMember>::operator()(
|
||||
Element* element) const
|
||||
{
|
||||
return &(element->*LinkMember);
|
||||
}
|
||||
|
||||
|
||||
template<typename Key>
|
||||
bool
|
||||
MinMaxHeapCompare<Key>::operator()(Key a, Key b)
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
MIN_MAX_HEAP_CLASS_NAME::MinMaxHeap()
|
||||
:
|
||||
fMinElements(NULL),
|
||||
fMinLastElement(0),
|
||||
fMaxElements(NULL),
|
||||
fMaxLastElement(0),
|
||||
fSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
MIN_MAX_HEAP_CLASS_NAME::MinMaxHeap(int initialSize)
|
||||
:
|
||||
fMinElements(NULL),
|
||||
fMinLastElement(0),
|
||||
fMaxElements(NULL),
|
||||
fMaxLastElement(0),
|
||||
fSize(0)
|
||||
{
|
||||
_GrowHeap(initialSize);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
MIN_MAX_HEAP_CLASS_NAME::~MinMaxHeap()
|
||||
{
|
||||
free(fMinElements);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
Element*
|
||||
MIN_MAX_HEAP_CLASS_NAME::PeekMinimum() const
|
||||
{
|
||||
if (fMinLastElement > 0)
|
||||
return fMinElements[0];
|
||||
else if (fMaxLastElement > 0) {
|
||||
ASSERT(fMaxLastElement == 1);
|
||||
return fMaxElements[0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
Element*
|
||||
MIN_MAX_HEAP_CLASS_NAME::PeekMaximum() const
|
||||
{
|
||||
if (fMaxLastElement > 0)
|
||||
return fMaxElements[0];
|
||||
else if (fMinLastElement > 0) {
|
||||
ASSERT(fMinLastElement == 1);
|
||||
return fMinElements[0];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
const Key&
|
||||
MIN_MAX_HEAP_CLASS_NAME::GetKey(Element* element)
|
||||
{
|
||||
return sGetLink(element)->fKey;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::ModifyKey(Element* element, Key newKey)
|
||||
{
|
||||
MinMaxHeapLink<Element, Key>* link = sGetLink(element);
|
||||
|
||||
Key oldKey = link->fKey;
|
||||
link->fKey = newKey;
|
||||
|
||||
if (!sCompare(newKey, oldKey) && !sCompare(oldKey, newKey))
|
||||
return;
|
||||
|
||||
if (sCompare(newKey, oldKey) ^ !link->fMinTree)
|
||||
_MoveUp(link);
|
||||
else
|
||||
_MoveDown(link);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::RemoveMinimum()
|
||||
{
|
||||
if (fMinLastElement == 0) {
|
||||
ASSERT(fMaxLastElement == 1);
|
||||
RemoveMaximum();
|
||||
return;
|
||||
}
|
||||
|
||||
#if KDEBUG
|
||||
Element* element = PeekMinimum();
|
||||
MinMaxHeapLink<Element, Key>* link = sGetLink(element);
|
||||
ASSERT(link->fIndex != -1);
|
||||
link->fIndex = -1;
|
||||
#endif
|
||||
|
||||
_RemoveLast(true);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::RemoveMaximum()
|
||||
{
|
||||
if (fMaxLastElement == 0) {
|
||||
ASSERT(fMinLastElement == 1);
|
||||
RemoveMinimum();
|
||||
return;
|
||||
}
|
||||
|
||||
#if KDEBUG
|
||||
Element* element = PeekMaximum();
|
||||
MinMaxHeapLink<Element, Key>* link = sGetLink(element);
|
||||
ASSERT(link->fIndex != -1);
|
||||
link->fIndex = -1;
|
||||
#endif
|
||||
|
||||
_RemoveLast(false);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
status_t
|
||||
MIN_MAX_HEAP_CLASS_NAME::Insert(Element* element, Key key)
|
||||
{
|
||||
if (min_c(fMinLastElement, fMaxLastElement) == fSize) {
|
||||
ASSERT(max_c(fMinLastElement, fMaxLastElement) == fSize);
|
||||
status_t result = _GrowHeap();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
}
|
||||
|
||||
ASSERT(fMinLastElement < fSize || fMaxLastElement < fSize);
|
||||
|
||||
MinMaxHeapLink<Element, Key>* link = sGetLink(element);
|
||||
|
||||
ASSERT(link->fIndex == -1);
|
||||
|
||||
link->fMinTree = fMinLastElement < fMaxLastElement;
|
||||
|
||||
int& lastElement = link->fMinTree ? fMinLastElement : fMaxLastElement;
|
||||
Element** tree = link->fMinTree ? fMinElements : fMaxElements;
|
||||
|
||||
tree[lastElement] = element;
|
||||
link->fIndex = lastElement++;
|
||||
link->fKey = key;
|
||||
|
||||
if (!_ChangeTree(link))
|
||||
_MoveUp(link);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
status_t
|
||||
MIN_MAX_HEAP_CLASS_NAME::_GrowHeap(int minimalSize)
|
||||
{
|
||||
minimalSize = minimalSize % 2 == 0 ? minimalSize : minimalSize + 1;
|
||||
int newSize = max_c(max_c(fSize * 4, 4), minimalSize);
|
||||
|
||||
size_t arraySize = newSize * sizeof(Element*);
|
||||
Element** newBuffer
|
||||
= reinterpret_cast<Element**>(realloc(fMinElements, arraySize));
|
||||
if (newBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
fMinElements = newBuffer;
|
||||
|
||||
newBuffer += newSize / 2;
|
||||
if (fMaxLastElement > 0)
|
||||
memcpy(newBuffer, fMinElements + fSize, fSize * sizeof(Element*));
|
||||
fMaxElements = newBuffer;
|
||||
|
||||
fSize = newSize / 2;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::_MoveUp(MinMaxHeapLink<Element, Key>* link)
|
||||
{
|
||||
Element** tree = link->fMinTree ? fMinElements : fMaxElements;
|
||||
while (true) {
|
||||
if (link->fIndex <= 0)
|
||||
break;
|
||||
|
||||
int parent = (link->fIndex - 1) / 2;
|
||||
bool isSmaller = sCompare(link->fKey, sGetLink(tree[parent])->fKey);
|
||||
if (isSmaller ^ !link->fMinTree) {
|
||||
ASSERT(sGetLink(tree[parent])->fIndex == parent);
|
||||
sGetLink(tree[parent])->fIndex = link->fIndex;
|
||||
|
||||
Element* element = tree[link->fIndex];
|
||||
tree[link->fIndex] = tree[parent];
|
||||
tree[parent] = element;
|
||||
|
||||
link->fIndex = parent;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::_MoveDown(MinMaxHeapLink<Element, Key>* link)
|
||||
{
|
||||
int current;
|
||||
|
||||
int lastElement = link->fMinTree ? fMinLastElement : fMaxLastElement;
|
||||
Element** tree = link->fMinTree ? fMinElements : fMaxElements;
|
||||
while (true) {
|
||||
current = link->fIndex;
|
||||
|
||||
int child = 2 * link->fIndex + 1;
|
||||
if (child < lastElement) {
|
||||
bool isSmaller = sCompare(sGetLink(tree[child])->fKey, link->fKey);
|
||||
if (isSmaller ^ !link->fMinTree)
|
||||
current = child;
|
||||
}
|
||||
|
||||
child = 2 * link->fIndex + 2;
|
||||
if (child < lastElement) {
|
||||
bool isSmaller = sCompare(sGetLink(tree[child])->fKey,
|
||||
sGetLink(tree[current])->fKey);
|
||||
if (isSmaller ^ !link->fMinTree)
|
||||
current = child;
|
||||
}
|
||||
|
||||
if (link->fIndex == current)
|
||||
break;
|
||||
|
||||
ASSERT(sGetLink(tree[current])->fIndex == current);
|
||||
sGetLink(tree[current])->fIndex = link->fIndex;
|
||||
|
||||
Element* element = tree[link->fIndex];
|
||||
tree[link->fIndex] = tree[current];
|
||||
tree[current] = element;
|
||||
|
||||
link->fIndex = current;
|
||||
}
|
||||
|
||||
if (2 * link->fIndex + 1 >= lastElement)
|
||||
_ChangeTree(link);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
bool
|
||||
MIN_MAX_HEAP_CLASS_NAME::_ChangeTree(MinMaxHeapLink<Element, Key>* link)
|
||||
{
|
||||
int otherLastElement = link->fMinTree ? fMaxLastElement : fMinLastElement;
|
||||
|
||||
Element** currentTree = link->fMinTree ? fMinElements : fMaxElements;
|
||||
Element** otherTree = link->fMinTree ? fMaxElements : fMinElements;
|
||||
|
||||
if (otherLastElement <= 0) {
|
||||
ASSERT(link->fMinTree ? fMinLastElement : fMaxLastElement == 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT((link->fIndex - 1) / 2 < otherLastElement);
|
||||
|
||||
Element* predecessor;
|
||||
if (2 * link->fIndex + 1 < otherLastElement) {
|
||||
predecessor = otherTree[2 * link->fIndex + 1];
|
||||
ASSERT(sGetLink(predecessor)->fIndex == 2 * link->fIndex + 1);
|
||||
} else if (link->fIndex < otherLastElement) {
|
||||
predecessor = otherTree[link->fIndex];
|
||||
ASSERT(sGetLink(predecessor)->fIndex == link->fIndex);
|
||||
} else {
|
||||
predecessor = otherTree[(link->fIndex - 1) / 2];
|
||||
ASSERT(sGetLink(predecessor)->fIndex == (link->fIndex - 1) / 2);
|
||||
}
|
||||
MinMaxHeapLink<Element, Key>* predecessorLink = sGetLink(predecessor);
|
||||
|
||||
bool isSmaller = sCompare(predecessorLink->fKey, link->fKey);
|
||||
if (isSmaller ^ !link->fMinTree) {
|
||||
Element* element = currentTree[link->fIndex];
|
||||
currentTree[link->fIndex] = otherTree[predecessorLink->fIndex];
|
||||
otherTree[predecessorLink->fIndex] = element;
|
||||
|
||||
int index = link->fIndex;
|
||||
link->fIndex = predecessorLink->fIndex;
|
||||
predecessorLink->fIndex = index;
|
||||
|
||||
predecessorLink->fMinTree = !predecessorLink->fMinTree;
|
||||
link->fMinTree = !link->fMinTree;
|
||||
|
||||
_MoveUp(link);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
void
|
||||
MIN_MAX_HEAP_CLASS_NAME::_RemoveLast(bool minTree)
|
||||
{
|
||||
bool deleteMin = fMaxLastElement < fMinLastElement;
|
||||
|
||||
Element** tree = deleteMin ? fMinElements : fMaxElements;
|
||||
int& lastElement = deleteMin ? fMinLastElement : fMaxLastElement;
|
||||
|
||||
ASSERT(lastElement > 0);
|
||||
lastElement--;
|
||||
if (lastElement == 0 && deleteMin == minTree)
|
||||
return;
|
||||
|
||||
Element* element = tree[lastElement];
|
||||
|
||||
if (minTree)
|
||||
fMinElements[0] = element;
|
||||
else
|
||||
fMaxElements[0] = element;
|
||||
|
||||
MinMaxHeapLink<Element, Key>* link = sGetLink(element);
|
||||
link->fIndex = 0;
|
||||
link->fMinTree = minTree;
|
||||
_MoveDown(link);
|
||||
}
|
||||
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
Compare MIN_MAX_HEAP_CLASS_NAME::sCompare;
|
||||
|
||||
MIN_MAX_HEAP_TEMPLATE_LIST
|
||||
GetLink MIN_MAX_HEAP_CLASS_NAME::sGetLink;
|
||||
|
||||
|
||||
#endif // KERNEL_UTIL_MIN_MAX_HEAP_H
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -18,22 +20,34 @@ atomic_pointer_test_and_set(PointerType** _pointer, const PointerType* set,
|
||||
const PointerType* test)
|
||||
{
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_test_and_set((vint32*)_pointer, (int32)set,
|
||||
return (PointerType*)atomic_test_and_set((int32*)_pointer, (int32)set,
|
||||
(int32)test);
|
||||
#else
|
||||
return (PointerType*)atomic_test_and_set64((vint64*)_pointer, (int64)set,
|
||||
return (PointerType*)atomic_test_and_set64((int64*)_pointer, (int64)set,
|
||||
(int64)test);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename PointerType> PointerType*
|
||||
atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
atomic_pointer_get_and_set(PointerType** _pointer, const PointerType* set)
|
||||
{
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_set((vint32*)_pointer, (int32)set);
|
||||
return (PointerType*)atomic_get_and_set((int32*)_pointer, (int32)set);
|
||||
#else
|
||||
return (PointerType*)atomic_set64((vint64*)_pointer, (int64)set);
|
||||
return (PointerType*)atomic_get_and_set64((int64*)_pointer, (int64)set);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename PointerType> void
|
||||
atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
{
|
||||
ASSERT((addr_t(_pointer) & (sizeof(PointerType*) - 1)) == 0);
|
||||
#if LONG_MAX == INT_MAX
|
||||
atomic_set((int32*)_pointer, (int32)set);
|
||||
#else
|
||||
atomic_set64((int64*)_pointer, (int64)set);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -41,10 +55,11 @@ atomic_pointer_set(PointerType** _pointer, const PointerType* set)
|
||||
template<typename PointerType> PointerType*
|
||||
atomic_pointer_get(PointerType** _pointer)
|
||||
{
|
||||
ASSERT((addr_t(_pointer) & (sizeof(PointerType*) - 1)) == 0);
|
||||
#if LONG_MAX == INT_MAX
|
||||
return (PointerType*)atomic_get((vint32*)_pointer);
|
||||
return (PointerType*)atomic_get((int32*)_pointer);
|
||||
#else
|
||||
return (PointerType*)atomic_get64((vint64*)_pointer);
|
||||
return (PointerType*)atomic_get64((int64*)_pointer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user