interface.cpp

00001
00002 /***************************************************************************
00003  *  interface.cpp - BlackBoard Interface
00004  *
00005  *  Created: Mon Oct 09 18:54:50 2006
00006  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023
00024 #include <interface/interface.h>
00025
00026 #include <interface/mediators/interface_mediator.h>
00027 #include <interface/mediators/message_mediator.h>
00028 #include <core/threading/refc_rwlock.h>
00029 #include <core/exceptions/system.h>
00030
00031 #include <cstring>
00032 #include <cstdio>
00033 #include <cstdlib>
00034 #include <typeinfo>
00035
00036 namespace fawkes {
00037 
00038 /** @class InterfaceWriteDeniedException <interface/interface.h>
00039  * This exception is thrown if a write has been attempted on a read-only interface.
00040  * @see Interface::write()
00041  * @ingroup Exceptions
00042  */
00043 
00044 /** Constructor.
00045  * @param type type of the interface which caused the exception
00046  * @param id id of the interface which caused the exception
00047  * @param msg additional informative message
00048  */
00049 InterfaceWriteDeniedException::InterfaceWriteDeniedException(const char *type,
00050                                                              const char *id,
00051                                                              const char *msg)
00052   : Exception("This interface instance '%s' of type '%s' is not opened for writing. %s",
00053               id, type, msg)
00054 {
00055 }
00056 
00057 /** @class InterfaceMessageEnqueueException <interface/interface.h>
00058  * This exception is thrown if a write has been attempted on a read-only interface.
00059  * @see Interface::write()
00060  * @ingroup Exceptions
00061  */
00062 
00063 /** Constructor.
00064  * @param type type of the interface which caused the exception
00065  * @param id id of the interface which caused the exception
00066  */
00067 InterfaceMessageEnqueueException::InterfaceMessageEnqueueException(const char *type,
00068                                                                    const char *id)
00069   : Exception("This interface instance '%s' of type '%s' IS opened for writing, but "
00070               "messages can only be enqueued on reading interfaces.", id, type)
00071 {
00072 }
00073 
00074 /** @class InterfaceInvalidMessageException <interface/interface.h>
00075  * This exception is thrown if a message has been queued in the interface which is
00076  * not recognized by the interface.
00077  * @ingroup Exceptions
00078  */
00079 
00080 /** Constructor.
00081  * @param interface interface that the invalid message was enqueued to
00082  * @param message enqueued message
00083  */
00084 InterfaceInvalidMessageException::InterfaceInvalidMessageException(const Interface *interface,
00085                                                                    const Message *message)
00086   : Exception("Message of type '%s' cannot be enqueued in interface of type '%s'",
00087               message->type(), interface->type())
00088 {
00089 }
00090
00091 
00092 /** @class InterfaceInvalidException <interface/interface.h>
00093  * This exception is thrown if an interface is invalid and it is attempted to call
00094  * read()/write().
00095  * @ingroup Exceptions
00096  */
00097 
00098 /** Constructor.
00099  * @param interface invalid interface that the operation was tried on
00100  * @param method the method that was tried to execute
00101  */
00102 InterfaceInvalidException::InterfaceInvalidException(const Interface *interface,
00103                                                      const char *method)
00104   : Exception("The interface %s (instance serial %u) is invalid. You cannot call %s anymore.",
00105               interface->uid(), interface->serial(), method)
00106 {
00107 }
00108
00109 
00110 /** @class Interface <interface/interface.h>
00111  * Base class for all Fawkes BlackBoard interfaces.
00112  * Never use directly. Use interface generator to create interfaces.
00113  *
00114  * Interfaces are identified by a type and an ID. The type is just a textual
00115  * representation of the class name. The ID identifies a specific instance of this
00116  * interface type. Additionally each interface has a hash. The hash is an MD5
00117  * digest of the XML config file that was fed to the interface generator to
00118  * create the interface. It is used to detect incompatible versions of the same
00119  * interface type.
00120  *
00121  * @author Tim Niemueller
00122  */
00123 
00124 /** @var Interface::data_ptr
00125  * Pointer to local memory storage
00126  */
00127 
00128 /** @var Interface::data_size
00129  * Minimal data size to hold data storage.
00130  */
00131 
00132 /** @fn bool Interface::message_valid(const Message *message) const = 0
00133  * Check if the message is valid and can be enqueued.
00134  * @param message The message to check
00135  * @return true, if the message is valid and may be enqueued, false otherwise
00136  *
00137  * @fn bool Interface::create_message(const char *type) const = 0
00138  * Create message based on type name.
00139  * This will create a new message of the given type. The type must be given without
00140  * the InterfaceName:: prefix but just the plain class name of the message.
00141  * @param type message type
00142  * @return message of the given type, empty
00143  * @exception UnknownTypeException thrown if this interface cannot create a message
00144  * of the given type.
00145  *
00146  * @fn void Interface::copy_values(const Interface *interface) = 0
00147  * Copy values from another interface.
00148  * The operation will only succeed if the supplied interface is of the same
00149  * type as this instance.
00150  * @param interface interface to copy from
00151  */
00152 
00153 /** Constructor */
00154 Interface::Interface()
00155 {
00156   __write_access = false;
00157   __rwlock = NULL;
00158   __valid = true;
00159   __next_message_id = 0;
00160   __num_fields = 0;
00161   __fieldinfo_list   = NULL;
00162   __messageinfo_list = NULL;
00163   memset(__hash, 0, __INTERFACE_HASH_SIZE);
00164   memset(__hash_printable, 0, __INTERFACE_HASH_SIZE * 2 + 1);
00165
00166   data_ptr  = NULL;
00167   data_size = 0;
00168
00169   __message_queue = new MessageQueue();
00170 }
00171
00172 
00173 /** Destructor */
00174 Interface::~Interface()
00175 {
00176   if ( __rwlock) __rwlock->unref();
00177   delete __message_queue;
00178   // free fieldinfo list
00179   interface_fieldinfo_t *finfol = __fieldinfo_list;
00180   while ( finfol ) {
00181     __fieldinfo_list = __fieldinfo_list->next;
00182     free(finfol);
00183     finfol = __fieldinfo_list;
00184   }
00185   // free messageinfo list
00186   interface_messageinfo_t *minfol = __messageinfo_list;
00187   while ( minfol ) {
00188     __messageinfo_list = __messageinfo_list->next;
00189     free(minfol);
00190     minfol = __messageinfo_list;
00191   }
00192 }
00193 
00194 /** Get interface hash.
00195  * The interface is a unique version identifier of an interface. It is the has of
00196  * the input XML file during the generation of the interface. It is meant to be used
00197  * to ensure that all sides are using the exact same version of an interface.
00198  * @return constant byte string containing the hash value of hash_size() length
00199  */
00200 const unsigned char *
00201 Interface::hash() const
00202 {
00203   return __hash;
00204 }
00205
00206 
00207 /** Get printable interface hash.
00208  * @return printable version of hash()
00209  */
00210 const char *
00211 Interface::hash_printable() const
00212 {
00213   return __hash_printable;
00214 }
00215
00216 
00217 /** Set hash. Never use directly.
00218  * @param ihash interface hash
00219  */
00220 void
00221 Interface::set_hash(unsigned char *ihash)
00222 {
00223   memcpy(__hash, ihash, __INTERFACE_HASH_SIZE);
00224   for (size_t s = 0; s < __INTERFACE_HASH_SIZE; ++s) {
00225     snprintf(&__hash_printable[s*2], 3, "%02X", __hash[s]);
00226   }
00227 }
00228
00229 
00230 /** Add an entry to the field info list.
00231  * Never use directly, use the interface generator instead. The info list
00232  * is used for introspection purposes to allow for iterating over all fields
00233  * of an interface.
00234  * @param type field type
00235  * @param name name of the field, this is referenced, not copied
00236  * @param length length of the field
00237  * @param value pointer to the value in the data struct
00238  */
00239 void
00240 Interface::add_fieldinfo(interface_fieldtype_t type, const char *name,
00241                          size_t length, void *value)
00242 {
00243   interface_fieldinfo_t *infol = __fieldinfo_list;
00244   interface_fieldinfo_t *newinfo = (interface_fieldinfo_t *)malloc(sizeof(interface_fieldinfo_t));
00245
00246   newinfo->type   = type;
00247   newinfo->name   = name;
00248   newinfo->length = length;
00249   newinfo->value  = value;
00250   newinfo->next   = NULL;
00251
00252   if ( infol == NULL ) {
00253     // first entry
00254     __fieldinfo_list = newinfo;
00255   } else {
00256     // append to list
00257     while ( infol->next != NULL ) {
00258       infol = infol->next;
00259     }
00260     infol->next = newinfo;
00261   }
00262
00263   ++__num_fields;
00264 }
00265
00266 
00267 /** Add an entry to the message info list.
00268  * Never use directly, use the interface generator instead. The info list
00269  * is used for introspection purposes to allow for iterating over all message
00270  * types of an interface.
00271  * @param type the type of the message
00272  */
00273 void
00274 Interface::add_messageinfo(const char *type)
00275 {
00276   interface_messageinfo_t *infol = __messageinfo_list;
00277   interface_messageinfo_t *newinfo = (interface_messageinfo_t *)malloc(sizeof(interface_messageinfo_t));
00278
00279   newinfo->type = type;
00280   newinfo->next = NULL;
00281
00282   if ( infol == NULL ) {
00283     // first entry
00284     __messageinfo_list = newinfo;
00285   } else {
00286     // append to list
00287     while ( infol->next != NULL ) {
00288       infol = infol->next;
00289     }
00290     infol->next = newinfo;
00291   }
00292 }
00293
00294 
00295 /** Obtain a list of textual representations of the message types
00296  * available for this interface.
00297  * @return the message types
00298  */
00299 std::list<const char *>
00300 Interface::get_message_types()
00301 {
00302   std::list<const char *> types;
00303   interface_messageinfo_t *cur = __messageinfo_list;
00304
00305   while ( cur != NULL ) {
00306     types.push_back(cur->type);
00307     cur = cur->next;
00308   }
00309
00310   return types;
00311 }
00312
00313 
00314 /** Get size of interface hash.
00315  * Returns the size in bytes of the interface hash. This depends on the used hash.
00316  * @return size of interface hash string
00317  */
00318 size_t
00319 Interface::hash_size() const
00320 {
00321   return __INTERFACE_HASH_SIZE;
00322 }
00323
00324 
00325 /** Get data chunk.
00326  * Use sparsely
00327  * @return const pointer to the data chunk
00328  */
00329 const void *
00330 Interface::datachunk() const
00331 {
00332   return data_ptr;
00333 }
00334
00335 
00336 /** Check if this is a writing instance.
00337  * @return true if this is a writing instance, false otherwise
00338  */
00339 bool
00340 Interface::is_writer() const
00341 {
00342   return __write_access;
00343 }
00344
00345 
00346 /** Mark this interface invalid.
00347  * An interface can become invalid, for example if the connection of a RemoteBlackBoard
00348  * dies. In this case the interface becomes invalid and successive read()/write() calls
00349  * will throw an InterfaceInvalidException.
00350  * @param valid true to mark the interface valid or false to mark it invalid
00351  */
00352 void
00353 Interface::set_validity(bool valid)
00354 {
00355   __rwlock->lock_for_write();
00356   __valid = valid;
00357   __rwlock->unlock();
00358 }
00359
00360 
00361 /** Check validity of interface.
00362  * @return true if interface is valid, false otherwise
00363  */
00364 bool
00365 Interface::is_valid() const
00366 {
00367   return __valid;
00368 }
00369
00370 
00371 /** Read from BlackBoard into local copy.
00372  * @exception InterfaceInvalidException thrown if the interface has been marked invalid
00373  */
00374 void
00375 Interface::read()
00376 {
00377   __rwlock->lock_for_read();
00378   if ( __valid ) {
00379     memcpy(data_ptr, __mem_data_ptr, data_size);
00380   } else {
00381     __rwlock->unlock();
00382     throw InterfaceInvalidException(this, "read()");
00383   }
00384   __rwlock->unlock();
00385 }
00386
00387 
00388 /** Write from local copy into BlackBoard memory.
00389  * @exception InterfaceInvalidException thrown if the interface has been marked invalid
00390  */
00391 void
00392 Interface::write()
00393 {
00394   if ( ! __write_access ) {
00395     throw InterfaceWriteDeniedException(__type, __id, "Cannot write.");
00396   }
00397
00398   __rwlock->lock_for_write();
00399   if ( __valid ) {
00400     memcpy(__mem_data_ptr, data_ptr, data_size);
00401   } else {
00402     __rwlock->unlock();
00403     throw InterfaceInvalidException(this, "write()");
00404   }
00405   __rwlock->unlock();
00406
00407   __interface_mediator->notify_of_data_change(this);
00408 }
00409
00410 
00411 /** Get data size.
00412  * @return size in bytes of data segment
00413  */
00414 unsigned int
00415 Interface::datasize() const
00416 {
00417   return data_size;
00418 }
00419
00420 
00421 /** Set type, ID and UID.
00422  * Sets type and ID, UID is generated automatically as Type::ID.
00423  * @param type string, a maxmimum of __INTERFACE_TYPE_SIZE bytes are copied
00424  * @param ID string, a maxmimum of __INTERFACE_ID_SIZE bytes are copied
00425  */
00426 void
00427 Interface::set_type_id(const char *type, const char *id)
00428 {
00429   strncpy(__type, type, __INTERFACE_TYPE_SIZE);
00430   strncpy(__id, id, __INTERFACE_ID_SIZE);
00431   snprintf(__uid, __INTERFACE_UID_SIZE, "%s::%s", type, id);
00432 }
00433
00434 
00435 /** Set instance serial.
00436  * @param instance_serial instance serial
00437  */
00438 void
00439 Interface::set_instance_serial(unsigned short instance_serial)
00440 {
00441   __instance_serial = instance_serial;
00442 }
00443
00444 
00445 /** Set mediators.
00446  * @param iface_mediator interface mediator
00447  * @param msg_mediator message mediator.
00448  */
00449 void
00450 Interface::set_mediators(InterfaceMediator *iface_mediator, MessageMediator *msg_mediator)
00451 {
00452   __interface_mediator = iface_mediator;
00453   __message_mediator   = msg_mediator;
00454 }
00455
00456 
00457 /** Set memory data.
00458  * @param serial mem serial
00459  * @param real_ptr pointer to whole chunk
00460  * @param data_ptr pointer to data chunk
00461  */
00462 void
00463 Interface::set_memory(unsigned int serial, void *real_ptr, void *data_ptr)
00464 {
00465   __mem_serial   = serial;
00466   __mem_real_ptr = real_ptr;
00467   __mem_data_ptr = data_ptr;
00468 }
00469
00470 
00471 /** Set read/write info.
00472  * @param write_access true to enable write access, false for read-only
00473  * @param rwlock read/write lock for this interface
00474  */
00475 void
00476 Interface::set_readwrite(bool write_access, RefCountRWLock *rwlock)
00477 {
00478   __write_access = write_access;
00479   __rwlock       = rwlock;
00480 }
00481
00482 
00483 /** Check equality of two interfaces.
00484  * Two interfaces are the same if their types and identifiers are equal.
00485  * This does not mean that both interfaces are the very same instance for accessing
00486  * the BlackBoard. Instead this just means that both instances will access the same
00487  * chunk of memory in the BlackBoard and the instances MAY be the same.
00488  * If you want to know if two instances are exactly the same compare the instance
00489  * serials using the serial() method.
00490  * @param comp interface to compare current instance with
00491  * @return true, if interfaces point to the same data, false otherwise
00492  */
00493 bool
00494 Interface::operator==(Interface &comp) const
00495 {
00496   return ( (strncmp(__type, comp.__type, sizeof(__type)) == 0) &&
00497            (strncmp(__id, comp.__id, sizeof(__id)) == 0) );
00498 }
00499
00500 
00501 /** Check if interface is of given type.
00502  * @param interface_type type to query
00503  * @return true, if current instance is of given type, false otherwise
00504  */
00505 bool
00506 Interface::oftype(const char *interface_type) const
00507 {
00508   return (strncmp(this->__type, interface_type, sizeof(this->__type)) == 0);
00509 }
00510
00511 
00512 /** Get type of interface.
00513  * @return string with the type of the interface.
00514  */
00515 const char *
00516 Interface::type() const
00517 {
00518   return __type;
00519 }
00520
00521 
00522 /** Get identifier of interface.
00523  * @return string with the identifier of the interface.
00524  */
00525 const char *
00526 Interface::id() const
00527 {
00528   return __id;
00529 }
00530
00531 
00532 /** Get unique identifier of interface.
00533  * As the name suggests this ID denotes a unique memory instance of this interface
00534  * in the blackboard. It is provided by the system and currently returns a string
00535  * of the form "type::id", where type is replaced by the type returned by type() and
00536  * id is the ID returned by id().
00537  * @return string with the unique identifier of the interface.
00538  */
00539 const char *
00540 Interface::uid() const
00541 {
00542   return __uid;
00543 }
00544
00545 
00546 /** Get instance serial of interface.
00547  * @return instance serial of the interface.
00548  */
00549 unsigned short
00550 Interface::serial() const
00551 {
00552   return __instance_serial;
00553 }
00554
00555 
00556 /** Get memory serial of interface.
00557  * @return memory serial of interface
00558  */
00559 unsigned int
00560 Interface::mem_serial() const
00561 {
00562   return __mem_serial;
00563 }
00564
00565 
00566 /** Set from a raw data chunk.
00567  * This allows for setting the interface data from a raw chunk. This is not useful
00568  * in general but only in rare situations like network transmission. Do not use it unless
00569  * you really know what you are doing. The method expects the chunk to be exactly of the
00570  * size returned by datasize(). No check is done, a segfault will most likely occur
00571  * if you provide invalid data.
00572  * @param chunk data chunk, must be exactly of the size that is returned by datasize()
00573  */
00574 void
00575 Interface::set_from_chunk(void *chunk)
00576 {
00577   // This could be checked but should never happen with our generated interfaces anyway
00578   // if ( data_ptr == NULL ) throw NullPointerException("Interface not initialized");
00579
00580   memcpy(data_ptr, chunk, data_size);
00581 }
00582 
00583 /** Check if there is a writer for the interface.
00584  * Use this method to determine if there is any open instance of the interface
00585  * that is writing to the interface. This can also be the queried interface
00586  * instance.
00587  */
00588 bool
00589 Interface::has_writer() const
00590 {
00591   return __interface_mediator->exists_writer(this);
00592 }
00593
00594 
00595 /** Get the number of readers.
00596  * Use this method to determine how many reading instances of the interface
00597  * currently exist. If the current instance is a reading instance it will
00598  * be included in the count number. To determine if you are the last man having
00599  * this interface you can use the following code:
00600  * @code
00601  * // for a writing instance:
00602  * if ( interface->num_readers == 0 ) {
00603  *   // we are the last one to have this interface open
00604  * }
00605  *
00606  * // for a reading instance:
00607  * if ( ! interface->has_writer() && (interface->num_readers() == 0) ) {
00608  *   // we are the last one to have this interface open
00609  * }
00610  * @endcode
00611  * Note that this can result in a race condition. You have to be registered as
00612  * a BlackBoardEventListener to be sure that you are really the last.
00613  */
00614 unsigned int
00615 Interface::num_readers() const
00616 {
00617   return __interface_mediator->num_readers(this);
00618 }
00619
00620 
00621 /** Enqueue message at end of queue.
00622  * This appends the given message to the queue and transmits the message via the
00623  * message mediator. The message is afterwards owned by the other side and will be
00624  * unrefed and freed as soon as it has been processed. If you want to keep this
00625  * message to read a feedback status you have to reference it _before_ enqueuing
00626  * it!
00627  * This can only be called on a reading interface instance.
00628  * @param message Message to enqueue.
00629  * @return message id after message has been queued
00630  * @exception MessageAlreadyQueuedException thrown if the message has already been
00631  * enqueued to an interface.
00632  */
00633 unsigned int
00634 Interface::msgq_enqueue(Message *message)
00635 {
00636   if ( __write_access ) {
00637     throw InterfaceMessageEnqueueException(__type, __id);
00638   }
00639
00640   if ( message_valid(message) ) {
00641     message->set_interface(this);
00642     message->set_id(next_msg_id());
00643     // transmit might change the message id!
00644     __message_mediator->transmit(message);
00645     unsigned int msgid = message->id();
00646     message->unref();
00647     return msgid;
00648   } else {
00649     throw InterfaceInvalidMessageException(this, message);
00650   }
00651 }
00652
00653 
00654 /** Enqueue copy of message at end of queue.
00655  * This method creates a copy of the message and enqueues it. Note that this way
00656  * you cannot receive status message in the message, because the other side will not
00657  * use your message instance but a copy instead.
00658  *
00659  * This is particularly useful if you call from an environment with automatic garbage
00660  * collection that does not honor the referencing feature of message but rather just
00661  * deletes it.
00662  * This can only be called on a reading interface instance.
00663  * @param message Message to enqueue.
00664  * @return message id after message has been queued
00665  * @exception MessageAlreadyQueuedException thrown if the message has already been
00666  * enqueued to an interface.
00667  */
00668 unsigned int
00669 Interface::msgq_enqueue_copy(Message *message)
00670 {
00671   if ( __write_access ) {
00672     throw InterfaceMessageEnqueueException(__type, __id);
00673   }
00674   if ( message == NULL ) {
00675     throw NullPointerException("Message may not be NULL");
00676   }
00677
00678   if ( message_valid(message) ) {
00679     Message *mcopy = message->clone();
00680     mcopy->set_interface(this);
00681     mcopy->set_id(next_msg_id());
00682     __message_mediator->transmit(mcopy);
00683     unsigned int msgid = mcopy->id();
00684     mcopy->unref();
00685     message->set_id(msgid);
00686     return msgid;
00687   } else {
00688     throw InterfaceInvalidMessageException(this, message);
00689   }
00690 }
00691
00692 
00693 /** Enqueue message.
00694  * This will enqueue the message without transmitting it via the message mediator.
00695  * This can only be called on a writing interface instance.
00696  * @param message message to enqueue
00697  */
00698 void
00699 Interface::msgq_append(Message *message)
00700 {
00701   if ( ! __write_access ) {
00702     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00703                                         "reading instance of an interface (append).");
00704   }
00705
00706   __message_queue->append(message);
00707 }
00708
00709 
00710 /** Remove message from queue.
00711  * Removes the given message from the queue. Note that if you unref()ed the message
00712  * after insertion this will most likely delete the object. It is not safe to use the
00713  * message after removing it from the queue in general. Know what you are doing if
00714  * you want to use it.
00715  * This can only be called on a writing interface instance.
00716  * @param message Message to remove.
00717  */
00718 void
00719 Interface::msgq_remove(Message *message)
00720 {
00721   if ( ! __write_access ) {
00722     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00723                                         "reading instance of an interface (remove msg).");
00724   }
00725
00726   return __message_queue->remove(message);
00727 }
00728
00729 
00730 /** Remove message from queue.
00731  * Removes message with the given ID from the queue.
00732  * @param message_id Message ID to remove.
00733  * This can only be called on a writing interface instance.
00734  */
00735 void
00736 Interface::msgq_remove(unsigned int message_id)
00737 {
00738   if ( ! __write_access ) {
00739     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00740                                         "reading instance of an interface (remove id).");
00741   }
00742
00743   return __message_queue->remove(message_id);
00744 }
00745
00746 
00747 /** Get size of message queue.
00748  * This can only be called on a writing interface instance.
00749  * @return number of messages in queue.
00750  */
00751 unsigned int
00752 Interface::msgq_size()
00753 {
00754   if ( ! __write_access ) {
00755     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00756                                         "reading instance of an interface (size).");
00757   }
00758
00759   return __message_queue->size();
00760 }
00761
00762 
00763 /** Check if queue is empty.
00764  * This can only be called on a writing interface instance.
00765  * @return true if queue is empty, false otherwise
00766  */
00767 bool
00768 Interface::msgq_empty()
00769 {
00770   if ( ! __write_access ) {
00771     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00772                                         "reading instance of an interface (empty).");
00773   }
00774
00775   return __message_queue->empty();
00776 }
00777
00778 
00779 /** Flush all messages.
00780  * Deletes all messages from the queue.
00781  * This can only be called on a writing interface instance.
00782  */
00783 void
00784 Interface::msgq_flush()
00785 {
00786   if ( ! __write_access ) {
00787     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00788                                         "reading instance of an interface (flush).");
00789   }
00790
00791   __message_queue->flush();
00792 }
00793
00794 
00795 /** Lock message queue.
00796  * Lock the message queue. You have to do this before using the iterator safely.
00797  * This can only be called on a writing interface instance.
00798  */
00799 void
00800 Interface::msgq_lock()
00801 {
00802   if ( ! __write_access ) {
00803     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00804                                         "reading instance of an interface (lock).");
00805   }
00806
00807   __message_queue->lock();
00808 }
00809
00810 
00811 /** Try to lock message queue.
00812  * Try to lock the message queue. Returns immediately and does not wait for lock.
00813  * @return true, if the lock has been aquired, false otherwise.
00814  * @see lock()
00815  * This can only be called on a writing interface instance.
00816  */
00817 bool
00818 Interface::msgq_try_lock()
00819 {
00820   if ( ! __write_access ) {
00821     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00822                                         "reading instance of an interface (try_lock).");
00823   }
00824
00825   return __message_queue->try_lock();
00826 }
00827
00828 
00829 /** Unlock message queue.
00830  * Give free the lock on the message queue.
00831  * This can only be called on a writing interface instance.
00832  */
00833 void
00834 Interface::msgq_unlock()
00835 {
00836   if ( ! __write_access ) {
00837     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00838                                         "reading instance of an interface (unlock).");
00839   }
00840
00841   __message_queue->unlock();
00842 }
00843 
00844 /** Get start iterator for message queue.
00845  * Not that you must have locked the queue before this operation!
00846  * This can only be called on a writing interface instance.
00847  * @return iterator to begin of message queue.
00848  * @exception NotLockedException thrown if message queue is not locked during this operation.
00849  */
00850 MessageQueue::MessageIterator
00851 Interface::msgq_begin()
00852 {
00853   if ( ! __write_access ) {
00854     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00855                                         "reading instance of an interface (begin).");
00856   }
00857
00858   return __message_queue->begin();
00859 }
00860
00861 
00862 /** Get end iterator for message queue.
00863  * Not that you must have locked the queue before this operation!
00864  * This can only be called on a writing interface instance.
00865  * @return iterator beyond end of message queue.
00866  * @exception NotLockedException thrown if message queue is not locked during this operation.
00867  */
00868 MessageQueue::MessageIterator
00869 Interface::msgq_end()
00870 {
00871   if ( ! __write_access ) {
00872     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00873                                         "reading instance of an interface (end).");
00874   }
00875
00876   return __message_queue->end();
00877 }
00878
00879 
00880 /** Get the first message from the message queue.
00881  * This can only be called on a writing interface instance.
00882  * @return first message in queue or NULL if there is none
00883  */
00884 Message *
00885 Interface::msgq_first()
00886 {
00887   if ( ! __write_access ) {
00888     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00889                                         "reading instance of an interface (first).");
00890   }
00891
00892   return __message_queue->first();
00893 }
00894 
00895 /** Erase first message from queue.
00896  * This can only be called on a writing interface instance.
00897  */
00898 void
00899 Interface::msgq_pop()
00900 {
00901   if ( ! __write_access ) {
00902     throw InterfaceWriteDeniedException(__type, __id, "Cannot work on message queue on "
00903                                         "reading instance of an interface (pop).");
00904   }
00905
00906   __message_queue->pop();
00907 }
00908
00909 
00910 /** Get iterator over all fields of this interface instance.
00911  * @return field iterator pointing to the very first value
00912  */
00913 InterfaceFieldIterator
00914 Interface::fields()
00915 {
00916   return InterfaceFieldIterator(__fieldinfo_list);
00917 }
00918
00919 
00920 /** Invalid iterator.
00921  * @return invalid iterator reprensenting the end.
00922  */
00923 InterfaceFieldIterator
00924 Interface::fields_end()
00925 {
00926   return InterfaceFieldIterator();
00927 }
00928
00929 
00930 /** Get the number of fields in the interface.
00931  * @return the number of fields
00932  */
00933 unsigned int
00934 Interface::num_fields()
00935 {
00936   return __num_fields;
00937 }
00938
00939 } // end namespace fawkes