blob: f68d40c0e5dcbb72447a64fa106f9fe14a7bb428 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
// -*- c++ -*-
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
// O S C L _ Q U E U E
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
/*! \addtogroup osclbase OSCL Base
* Additional osclbase comment
* @{
*/
/*! \file oscl_queue.h
\brief The file oscl_queue.h defines the template class Oscl_Queue. It is
similar to the STL::queue class, with some differences:
- less complete
- based on array rather than a deque
- some interfaces modeled on oscl_vector, for ease of transition
Memory allocation is abstracted through the use of an allocator template parameter.
*/
#ifndef OSCL_QUEUE_H_INCLUDED
#define OSCL_QUEUE_H_INCLUDED
#ifndef OSCL_BASE_H_INCLUDED
#include "oscl_base.h"
#endif
#ifndef OSCL_MEM_BASIC_FUNCTIONS_H_INCLUDED
#include "oscl_mem_basic_functions.h"
#endif
#ifndef OSCL_ASSERT_H_INCLUDED
#include "oscl_assert.h"
#endif
#ifndef OSCL_OPAQUE_TYPE_H_INCLUDED
#include "oscl_opaque_type.h"
#endif
/**
* Oscl_Queue_Base is a non-templatized base class for Oscl_Queue.
* The purpose of this base class is to avoid large inline routines
* in the Oscl_Queue implementation.
* This class is not intended for direct instantiation except by
* Oscl_Queue.
*/
class Oscl_Queue_Base
{
public:
/**
* Returns the size of the queue.
*/
uint32 size() const
{
return numelems;
}
/**
* Returns the allocated memory of the queue.
*/
uint32 capacity() const
{
return bufsize;
}
/**
* True if there are no elements in the queue
*/
bool empty() const
{
return numelems == 0;
}
/**
* Reallocates memory if necessary to a capacity of n elements.
* The main reason for reserve is efficiency. If you know the capacity to
* which your vector must grow, then it is more efficient to allocate the
* vector all at once rather than rely on the automatic reallocation scheme.
* This also helps cotrol the invalidation of iterators.
* @param n size of vector
*/
OSCL_IMPORT_REF void reserve(uint32 n) ;
protected:
//for use in default constructor. vtable is needed so this is a subroutine.
OSCL_IMPORT_REF void construct(Oscl_Opaque_Type_Alloc* aType);
//for use in constructor with pre-allocation for "n" elements.
OSCL_IMPORT_REF void construct(Oscl_Opaque_Type_Alloc* aType, uint32 n) ;
/**
* The destructor.
*/
virtual ~Oscl_Queue_Base()
{}
/**
* Like an explicit destructor call.
*/
OSCL_IMPORT_REF void destroy();
/**
* Inserts a new element at the end.
* Queue will be grown if necessary. If allocation fails, an OSCL_LEAVE will occur
* @param x new element
*/
OSCL_IMPORT_REF void push(const OsclAny* x) ;
/**
* Removes the first element
*/
OSCL_IMPORT_REF void pop() ;
/**
* Removes all elements.
*/
OSCL_IMPORT_REF void clear() ;
uint32 numelems; // number of valid entries in queue
uint32 bufsize; // size of elems
OsclAny* elems; // array holding the elements
uint32 sizeof_T;
uint32 ifront; // front of queue: removal point
uint32 irear; // just before back of queue: increment=>insertion point
private:
/**
* return a T* incremented by n.
*/
OsclAny* increment_T(OsclAny* p_T, int32 n) const
{
return (OsclAny*)((int32)p_T + n*sizeof_T);
}
/**
* Returns the first element.
*/
OsclAny* front()
{
return increment_T(elems, ifront);
}
Oscl_Opaque_Type_Alloc* pOpaqueType;
};
/**
* Oscl_Queue Class. A subset of STL::Queue methods.
* Oscl_Queue supports constant time insertion (at the end) and removal of
* elements at the front of the queue. It does not support
* insertion or removal of elements at the other ends or middle of the
* queue, nor random access to elements.
* * No iteration capability is [currently] supplied.
* * No assignment or copy capability is [currently] supplied.
* The number of elements in a queue can vary dynamically, and
* memory management is performed automatically.
*/
template<class T, class Alloc>
class Oscl_Queue
: public Oscl_Queue_Base
, public Oscl_Opaque_Type_Alloc
{
public:
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T& const_reference;
typedef uint32 size_type;
/**
* Creates an empty queue.
*/
Oscl_Queue() : Oscl_Queue_Base(), Oscl_Opaque_Type_Alloc()
{
sizeof_T = sizeof(T);
Oscl_Queue_Base::construct(this);
}
/**
* Creates an empty queue with capacity n.
* @param n creates a queue with n elements. The main reason for specifying n
* is efficiency. If you know the capacity to which your queue must grow, then
* it is more efficient to allocate the queue all at once rather than rely on
* the automatic reallocation scheme.
*/
Oscl_Queue(uint32 n) : Oscl_Queue_Base(), Oscl_Opaque_Type_Alloc()
{
sizeof_T = sizeof(T);
Oscl_Queue_Base::construct(this, n);
}
/**
* The destructor.
*/
virtual ~Oscl_Queue()
{
Oscl_Queue_Base::destroy();
}
/**
* Inserts a new element at the end.
* Queue will be grown if necessary. If allocation fails, an OSCL_LEAVE will occur
* @param x new element
*/
void push(const T& x)
{
Oscl_Queue_Base::push(&x);
}
/**
* Returns the first element.
*/
reference front()
{
OSCL_ASSERT(! empty());
return (reference)((pointer)elems)[ifront];
}
/**
* Returns the first element (const)
*/
const_reference front() const
{
OSCL_ASSERT(! empty());
return (const_reference)((pointer)elems)[ifront];
}
/**
* Removes the first element
*/
void pop()
{
Oscl_Queue_Base::pop();
}
/**
* Returns the last element: "back"
* (generally not too useful, but some debugging aids might
* want to find out what was just added)
*/
reference back()
{
OSCL_ASSERT(! empty());
return (reference)((pointer)elems)[irear];
}
/**
* Returns the last element (const)
*/
const_reference back() const
{
OSCL_ASSERT(! empty());
return (const_reference)((pointer)elems)[irear];
}
/**
* Removes all elements.
*/
void clear()
{
Oscl_Queue_Base::clear();
}
/**
* Return various iterators
* : not provided for queues. Paradigm is FIFO
*/
/**
* Erases the element pointed to by iterator pos.
* : not provided for queues. Paradigm is QUEUE.
*/
private:
Alloc defAlloc;
//from Oscl_Opaque_Type_Alloc
OsclAny* allocate(const uint32 size)
{
return defAlloc.allocate(size);
}
//from Oscl_Opaque_Type_Alloc
void deallocate(OsclAny* p)
{
defAlloc.deallocate(p);
}
//from Oscl_Opaque_Type_Alloc
void construct(OsclAny* p, const OsclAny* x)
{
OSCL_ASSERT(x);
new(p) value_type(*((T*)x));
}
//from Oscl_Opaque_Type_Alloc
void destroy(OsclAny* first)
{
OSCL_ASSERT(first);
OSCL_UNUSED_ARG(first);
//must use "pointer" instead of "T*" here to avoid ADS 1.2 compile error.
((pointer)first)->~T();
}
/***************************
* things we don't believe are needed
* -- private definitions to block implicit ones --
*/
/**
* The assignment operator --
* - private, to block use of implicit assignment
* - not actually implemented, don't believe it's needed
*/
Oscl_Queue<T, Alloc>& operator=(const Oscl_Queue<T, Alloc>& x)
{
// Do we need to copy a queue? Why...?
// .. unless there's a need, let's not bother with the
// complexity here..
// (need something here, we don't want implicit assignment either
OSCL_UNUSED_ARG(x);
OSCL_ASSERT(false);
return *this;
}
/**
* Copy Constructor.
* @param x queue class to copy, also for value passage as argument
* (but: why do we want to copy a queue??)
*/
Oscl_Queue(const Oscl_Queue<T, Alloc>& x)
: Oscl_Queue_Base(sizeof(T), this, this)
{
OSCL_UNUSED_ARG(x);
OSCL_ASSERT(false);
}
}; // end class oscl_queue
/*! @} */
#endif