/usr/include/ucommon/containers.h is in libucommon-dev 6.0.7-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This file is part of GNU uCommon C++.
//
// GNU uCommon C++ is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU uCommon C++ is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
/**
* Threadsafe object containers. This is used to better define
* object containers and manipulating classes which can be presumed to be
* fully threadsafe and thread-aware. This has to be defined separately
* to assure correct order of preceeding headers as well as to better
* organize the library for clarity. Most of these classes and templates
* work with classes derived from Object and LinkedObject and make use of
* conditional for time constrained acquisition of managed objects.
* @file ucommon/containers.h
*/
#ifndef _UCOMMON_CONTAINERS_H_
#define _UCOMMON_CONTAINERS_H_
#ifndef _UCOMMON_CONFIG_H_
#include <ucommon/platform.h>
#endif
#ifndef _UCOMMON_PROTOCOLS_H_
#include <ucommon/protocols.h>
#endif
#ifndef _UCOMMON_LINKED_H_
#include <ucommon/linked.h>
#endif
#ifndef _UCOMMON_MEMORY_H_
#include <ucommon/memory.h>
#endif
#ifndef _UCOMMON_THREAD_H_
#include <ucommon/thread.h>
#endif
NAMESPACE_UCOMMON
/**
* Linked allocator helper for linked_allocator template. This is used
* to alloc an array of typed objects tied to a free list in a single
* operation.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT LinkedAllocator : private Conditional
{
protected:
LinkedObject *freelist;
LinkedAllocator();
LinkedObject *get(void);
LinkedObject *get(timeout_t timeout);
void release(LinkedObject *node);
public:
/**
* Test if there is still objects in the free list.
* @return true if there are objects.
*/
operator bool();
/**
* Test if the free list is empty.
* @return true if the free list is empty.
*/
bool operator!();
};
/**
* A thread-safe buffer for serializing and streaming class data. While
* the queue and stack operate by managing lists of reference pointers to
* objects of various mixed kind, the buffer holds physical copies of objects
* that being passed through it, and all must be the same size. For this
* reason the buffer is normally used through the bufferof<type> template
* rather than stand-alone. The buffer is accessed in fifo order.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT Buffer : protected Conditional
{
private:
size_t bufsize, objsize;
caddr_t buf, head, tail;
unsigned objcount, limit;
protected:
/**
* Create a buffer to hold a series of objects.
* @param size of each object in buffer.
* @param count of objects in the buffer.
*/
Buffer(size_t typesize, size_t count);
/**
* Deallocate buffer and unblock any waiting threads.
*/
virtual ~Buffer();
/**
* Get the next object from the buffer.
* @param timeout to wait when buffer is empty in milliseconds.
* @return pointer to next object in the buffer or NULL if timed out.
*/
void *get(timeout_t timeout);
/**
* Get the next object from the buffer. This blocks until an object
* becomes available.
* @return pointer to next object from buffer.
*/
void *get(void);
/**
* Put (copy) an object into the buffer. This blocks while the buffer
* is full.
* @param data to copy into the buffer.
*/
void put(void *data);
/**
* Put (copy) an object into the buffer.
* @param data to copy into the buffer.
* @param timeout to wait if buffer is full.
* @return true if copied, false if timed out while full.
*/
bool put(void *data, timeout_t timeout);
/**
* Release must be called when we get an object from the buffer. This
* is because the pointer we return is a physical pointer to memory
* that is part of the buffer. The object we get cannot be removed or
* the memory modified while the object is being used.
*/
void release(void);
/**
* Copy the next object from the buffer. This blocks until an object
* becomes available. Buffer is auto-released.
* @param data pointer to copy into.
*/
void copy(void *data);
/**
* Copy the next object from the buffer. Buffer is auto-released.
* @param data pointer to copy into.
* @param timeout to wait when buffer is empty in milliseconds.
* @return true if object copied, or false if timed out.
*/
bool copy(void *data, timeout_t timeout);
/**
* Peek at pending data in buffer. This returns a pointer to
* objects relative to the head. In effect it is the same as
* get() for item = 0.
* @param item to examine in buffer.
* @return pointer to item or NULL if invalid item number.
*/
void *peek(unsigned item);
virtual void *invalid(void) const;
public:
/**
* Get the size of the buffer.
* @return size of the buffer.
*/
unsigned size(void);
/**
* Get the number of objects in the buffer currently.
* @return number of objects buffered.
*/
unsigned count(void);
/**
* Test if there is data waiting in the buffer.
* @return true if buffer has data.
*/
operator bool();
/**
* Test if the buffer is empty.
* @return true if the buffer is empty.
*/
bool operator!();
};
/**
* Manage a thread-safe queue of objects through reference pointers. This
* can be particularly interesting when used to enqueue/dequeue reference
* counted managed objects. Thread-safe access is managed through a
* conditional. Both lifo and fifo forms of queue access may be used. A
* pool of self-managed member objects are used to operate the queue. This
* queue is optimized for fifo access; while lifo is supported, it will be
* slow. If you need primarily lifo, you should use stack instead.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT Queue : protected OrderedIndex, protected Conditional
{
private:
mempager *pager;
LinkedObject *freelist;
size_t used;
class __LOCAL member : public OrderedObject
{
public:
member(Queue *q, ObjectProtocol *obj);
ObjectProtocol *object;
};
friend class member;
protected:
size_t limit;
virtual ObjectProtocol *invalid(void) const;
public:
/**
* Create a queue that uses a memory pager for internally managed
* member objects for a specified maximum number of object pointers.
* @param pager to use for internal member object or NULL to use heap.
* @param number of pointers that can be in the queue or 0 for unlimited.
* size limit.
*/
Queue(mempager *pager = NULL, size_t number = 0);
/**
* Destroy queue. If no mempager is used, then frees heap.
*/
~Queue();
/**
* Remove a specific object pointer for the queue. This can remove
* a member from any location in the queue, whether beginning, end, or
* somewhere in the middle. This also releases the object.
* @param object to remove.
* @return true if object was removed, false if not found.
*/
bool remove(ObjectProtocol *object);
/**
* Post an object into the queue by it's pointer. This can wait for
* a specified timeout if the queue is full, for example, for another
* thread to remove an object pointer. This also retains the object.
* @param object to post.
* @param timeout to wait if queue is full in milliseconds.
* @return true if object posted, false if queue full and timeout expired.
*/
bool post(ObjectProtocol *object, timeout_t timeout = 0);
/**
* Examine pending existing object in queue. Does not remove it.
* @param number of elements back.
* @return object in queue or NULL if invalid value.
*/
ObjectProtocol *get(unsigned offset = 0);
/**
* Get and remove last object posted to the queue. This can wait for
* a specified timeout of the queue is empty. The object is still
* retained and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object from queue or NULL if empty and timed out.
*/
ObjectProtocol *fifo(timeout_t timeout = 0);
/**
* Get and remove first object posted to the queue. This can wait for
* a specified timeout of the queue is empty. The object is still
* retained and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object from queue or NULL if empty and timed out.
*/
ObjectProtocol *lifo(timeout_t timeout = 0);
/**
* Get number of object points currently in the queue.
* @return number of objects in queue.
*/
size_t count(void);
};
/**
* Manage a thread-safe stack of objects through reference pointers. This
* Thread-safe access is managed through a conditional. This differs from
* the queue in lifo mode because delinking the last object is immediate,
* and because it has much less overhead. A pool of self-managed
* member objects are used to operate the stack.
* @author David Sugar <dyfet@gnutelephony.org>
*/
class __EXPORT Stack : protected Conditional
{
private:
LinkedObject *freelist, *usedlist;
mempager *pager;
size_t used;
class __LOCAL member : public LinkedObject
{
public:
member(Stack *s, ObjectProtocol *obj);
ObjectProtocol *object;
};
friend class member;
protected:
size_t limit;
virtual ObjectProtocol *invalid(void) const;
public:
/**
* Create a stack that uses a memory pager for internally managed
* member objects for a specified maximum number of object pointers.
* @param pager to use for internal member object or NULL to use heap.
* @param number of pointers that can be in the stack or 0 if unlimited.
*/
Stack(mempager *pager = NULL, size_t number = 0);
/**
* Destroy queue. If no pager is used, then frees heap.
*/
virtual ~Stack();
/**
* Remove a specific object pointer for the queue. This can remove
* a member from any location in the queue, whether beginning, end, or
* somewhere in the middle. This also releases the object.
* @param object to remove.
* @return true if object was removed, false if not found.
*/
bool remove(ObjectProtocol *object);
/**
* Push an object into the stack by it's pointer. This can wait for
* a specified timeout if the stack is full, for example, for another
* thread to remove an object pointer. This also retains the object.
* @param object to push.
* @param timeout to wait if stack is full in milliseconds.
* @return true if object pushed, false if stack full and timeout expired.
*/
bool push(ObjectProtocol *object, timeout_t timeout = 0);
/**
* Get and remove last object pushed on the stack. This can wait for
* a specified timeout of the stack is empty. The object is still
* retained and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object pulled from stack or NULL if empty and timed out.
*/
ObjectProtocol *pull(timeout_t timeout = 0);
/**
* Examine an existing object on the stack.
* @param offset to stack entry.
* @return object examined.
*/
ObjectProtocol *get(unsigned offset = 0);
/**
* Get number of object points currently in the stack.
* @return number of objects in stack.
*/
size_t count(void);
const ObjectProtocol *peek(timeout_t timeout = 0);
};
/**
* Linked allocator template to gather linked objects. This allocates the
* object pool in a single array as a single heap allocation, and releases
* the whole pool with a single delete when done. It is also threadsafe.
* The types used must be derived of LinkedObject.
* @author David Sugar <dyfet@gnutelephony.org>
*/
template <class T>
class linked_allocator : public LinkedAllocator
{
private:
T* array;
public:
inline linked_allocator(size_t size) : LinkedAllocator() {
array = new T[size];
for(unsigned i = 0; i < size; ++i)
array[i].enlist(&freelist);
}
~linked_allocator()
{delete[] array;};
inline T *get(void)
{return static_cast<T *>(LinkedAllocator::get());};
inline T *get(timeout_t timeout)
{return static_cast<T *>(LinkedAllocator::get(timeout));};
inline void release(T *node)
{LinkedAllocator::release(node);};
};
/**
* A templated typed class for buffering of objects. This operates as a
* fifo buffer of typed objects which are physically copied into the buffer.
* The objects that are buffered are accessed from allocated buffer space.
* As designed this may be used with multiple producer threads and one
* consumer thread. To use multiple consumers, one can copy the typed object
* from the buffer through the get pointer and then call release. The
* copied object can then be used safely. This is what the copy method is
* used for.
* @author David Sugar <dyfet@gnutelephony.org>
*/
template<class T>
class bufferof : public Buffer
{
public:
/**
* Create a buffer to hold a series of typed objects.
* @param count of typed objects in the buffer.
*/
inline bufferof(unsigned capacity) :
Buffer(sizeof(T), capacity) {};
/**
* Get the next typed object from the buffer. This blocks until an object
* becomes available.
* @return pointer to next typed object from buffer.
*/
inline T *get(void)
{return static_cast<T*>(get());};
/**
* Get the next typed object from the buffer.
* @param timeout to wait when buffer is empty in milliseconds.
* @return pointer to next typed object in the buffer or NULL if timed out.
*/
inline T *get(timeout_t timeout)
{return static_cast<T*>(get(timeout));};
/**
* Put (copy) a typed object into the buffer. This blocks while the buffer
* is full.
* @param object to copy into the buffer.
*/
inline void put(T *object)
{put(object);};
/**
* Put (copy) an object into the buffer.
* @param object to copy into the buffer.
* @param timeout to wait if buffer is full.
* @return true if copied, false if timed out while full.
*/
inline bool put(T *object, timeout_t timeout)
{return put(object, timeout);};
/**
* Copy the next typed object from the buffer. This blocks until an object
* becomes available.
* @param object pointer to copy typed object into.
*/
inline void copy(T *object)
{copy(object);};
/**
* Copy the next typed object from the buffer.
* @param object pointer to copy typed object into.
* @param timeout to wait when buffer is empty in milliseconds.
* @return true if object copied, or false if timed out.
*/
inline bool get(T *object, timeout_t timeout)
{return copy(object, timeout);};
/**
* Examine past item in the buffer. This is a typecast of the peek
* operation.
* @param item in buffer.
* @return item pointer if valid or NULL.
*/
inline const T& at(unsigned item)
{return static_cast<const T&>(Buffer::peek(item));};
/**
* Examine past item in the buffer. This is a typecast of the peek
* operation.
* @param item in buffer.
* @return item pointer if valid or NULL.
*/
inline T&operator[](unsigned item)
{return static_cast<T&>(Buffer::peek(item));};
inline T* operator()(unsigned offset = 0)
{return static_cast<T*>(Buffer::peek(offset));}
};
/**
* A templated typed class for thread-safe stack of object pointers. This
* allows one to use the stack class in a typesafe manner for a specific
* object type derived from Object rather than generically for any derived
* object class.
* @author David Sugar <dyfet@gnutelephony.org>
*/
template<class T>
class stackof : public Stack
{
public:
/**
* Create templated stack of typed objects.
* @param memory pool for internal use of stack.
* @param size of stack to construct. Uses 0 if no size limit.
*/
inline stackof(mempager *memory, size_t size = 0) : Stack(memory, size) {};
/**
* Remove a specific typed object pointer for the stack. This can remove
* a member from any location in the stack, whether beginning, end, or
* somewhere in the middle. This releases the object.
* @param object to remove.
* @return true if object was removed, false if not found.
*/
inline bool remove(T *object)
{return Stack::remove(object);};
/**
* Push a typed object into the stack by it's pointer. This can wait for
* a specified timeout if the queue is full, for example, for another
* thread to remove an object pointer. This retains the object.
* @param object to push.
* @param timeout to wait if queue is full in milliseconds.
* @return true if object pushed, false if queue full and timeout expired.
*/
inline bool push(T *object, timeout_t timeout = 0)
{return Stack::push(object);};
/**
* Get and remove last typed object posted to the stack. This can wait for
* a specified timeout of the stack is empty. The object is still retained
* and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object from queue or NULL if empty and timed out.
*/
inline T *pull(timeout_t timeout = 0)
{return static_cast<T *>(Stack::pull(timeout));};
/**
* Examine last typed object posted to the stack. This can wait for
* a specified timeout of the stack is empty.
* @param timeout to wait if empty in milliseconds.
* @return object in queue or NULL if empty and timed out.
*/
inline const T *peek(timeout_t timeout = 0)
{return static_cast<const T *>(Stack::peek(timeout));};
inline T* operator()(unsigned offset = 0)
{return static_cast<T*>(Stack::get(offset));}
/**
* Examine past item in the stack. This is a typecast of the peek
* operation.
* @param offset in stack.
* @return item pointer if valid or NULL.
*/
inline const T& at(unsigned offset = 0)
{return static_cast<const T&>(Stack::get(offset));};
/**
* Examine past item in the stack. This is a typecast of the peek
* operation.
* @param offset in stack.
* @return item pointer if valid or NULL.
*/
inline const T& operator[](unsigned offset)
{return static_cast<T&>(Stack::get(offset));};
};
/**
* A templated typed class for thread-safe queue of object pointers. This
* allows one to use the queue class in a typesafe manner for a specific
* object type derived from Object rather than generically for any derived
* object class.
* @author David Sugar <dyfet@gnutelephony.org>
*/
template<class T>
class queueof : public Queue
{
public:
/**
* Create templated queue of typed objects.
* @param memory pool for internal use by queue.
* @param size of queue to construct. Uses 0 if no size limit.
*/
inline queueof(mempager *memory, size_t size = 0) : Queue(memory, size) {};
/**
* Remove a specific typed object pointer for the queue. This can remove
* a member from any location in the queue, whether beginning, end, or
* somewhere in the middle. This releases the object.
* @param object to remove.
* @return true if object was removed, false if not found.
*/
inline bool remove(T *object)
{return Queue::remove(object);};
/**
* Post a typed object into the queue by it's pointer. This can wait for
* a specified timeout if the queue is full, for example, for another
* thread to remove an object pointer. This retains the object.
* @param object to post.
* @param timeout to wait if queue is full in milliseconds.
* @return true if object posted, false if queue full and timeout expired.
*/
inline bool post(T *object, timeout_t timeout = 0)
{return Queue::post(object);};
/**
* Get and remove first typed object posted to the queue. This can wait for
* a specified timeut of the queue is empty. The object is still retained
* and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object from queue or NULL if empty and timed out.
*/
inline T *fifo(timeout_t timeout = 0)
{return static_cast<T *>(Queue::fifo(timeout));};
/**
* Get and remove last typed object posted to the queue. This can wait for
* a specified timeout of the queue is empty. The object is still retained
* and must be released or deleted by the receiving function.
* @param timeout to wait if empty in milliseconds.
* @return object from queue or NULL if empty and timed out.
*/
inline T *lifo(timeout_t timeout = 0)
{return static_cast<T *>(Queue::lifo(timeout));};
/**
* Examine past item in the queue. This is a typecast of the peek
* operation.
* @param offset in queue.
* @return item pointer if valid or NULL.
*/
inline const T& at(unsigned offset = 0)
{return static_cast<const T&>(Queue::get(offset));};
/**
* Examine past item in the queue. This is a typecast of the peek
* operation.
* @param offset in queue.
* @return item pointer if valid or NULL.
*/
inline T& operator[](unsigned offset)
{return static_cast<T&>(Queue::get(offset));};
inline T* operator()(unsigned offset = 0)
{return static_cast<T*>(Queue::get(offset));}
};
/**
* Convenience type for using thread-safe object stacks.
*/
typedef Stack stack_t;
/**
* Convenience type for using thread-safe object fifo (queue).
*/
typedef Queue fifo_t;
END_NAMESPACE
#endif
|