winamp/Src/Plugins/Library/ml_transcode/LinkedQueue.cpp

139 lines
2.4 KiB
C++

#include "LinkedQueue.h"
LinkedQueue::LinkedQueue()
{
size=0;
head=NULL;
tail=NULL;
bm=NULL;
bmpos=0;
InitializeCriticalSection(&cs);
}
void LinkedQueue::lock()
{
EnterCriticalSection(&cs);
//wchar_t buf[100]; wsprintf(buf,L"Lock taken by %x",GetCurrentThreadId()); OutputDebugString(buf);
}
void LinkedQueue::unlock()
{
LeaveCriticalSection(&cs);
//wchar_t buf[100]; wsprintf(buf,L"Lock released by %x",GetCurrentThreadId()); OutputDebugString(buf);
}
LinkedQueue::~LinkedQueue()
{
lock();
QueueElement * q=head;
while(q) { QueueElement *p=q; q=q->next; delete p; }
unlock();
DeleteCriticalSection(&cs);
}
void LinkedQueue::Offer(void * e)
{
lock();
if(size==0) { size++; head=tail=new QueueElement(e); unlock(); return; }
tail->next=new QueueElement(e);
tail->next->prev=tail;
tail=tail->next;
size++;
bm=NULL;
unlock();
}
void * LinkedQueue::Poll()
{
lock();
if(size == 0) { unlock(); return NULL; }
size--;
void * r = head->elem;
QueueElement * q = head;
head=head->next;
if(head!=NULL) head->prev=NULL;
else tail=NULL;
delete q;
bm=NULL;
unlock();
return r;
}
void * LinkedQueue::Peek()
{
lock();
void * ret=head?head->elem:NULL;
unlock();
return ret;
}
QueueElement * LinkedQueue::Find(int x)
{
if(x>=size || x<0) return NULL;
if(x == 0) return head;
if(x == size-1) return tail;
if(!bm) { bm=head; bmpos=0; }
int diffh = x;
int difft = (size-1) - x;
int diffbm = x - bmpos;
diffbm>0?diffbm:-diffbm;
if(diffh < difft && diffh < diffbm) { bm=head; bmpos=0; }
else if(diffh >= difft && diffbm >= difft) { bm=tail; bmpos=size-1; }
while(bmpos > x && bm) { bm=bm->prev; bmpos--; }
while(bmpos < x && bm) { bm=bm->next; bmpos++; }
return bm;
}
void * LinkedQueue::Get(int pos)
{
lock();
QueueElement * e = Find(pos);
unlock();
return e?e->elem:NULL;
}
void LinkedQueue::Set(int pos, void * val)
{
lock();
QueueElement * e = Find(pos);
if(e) e->elem=val;
unlock();
}
void* LinkedQueue::Del(int pos)
{
lock();
QueueElement * e = Find(pos);
if(!e) { unlock(); return NULL; }
else if(size == 1) head=tail=NULL;
else if(e==head)
{
head=head->next;
head->prev=NULL;
}
else if(e==tail)
{
tail=tail->prev;
tail->next=NULL;
}
else
{
e->prev->next = e->next;
e->next->prev = e->prev;
}
size--;
bm=NULL;
unlock();
void * ret = e->elem;
delete e;
return ret;
}
int LinkedQueue::GetSize()
{
return size;
/*
lock();
int s = size;
unlock();
return s;*/
}