added new PriorityNotificationQueue, TimedNotificationQueue; added File::isDevice()

This commit is contained in:
Guenter Obiltschnig 2009-04-14 10:38:52 +00:00
parent 98eb0eb532
commit 095401e8e4
36 changed files with 1718 additions and 141 deletions

View File

@ -574,7 +574,6 @@
<File <File
RelativePath=".\include\Poco\Debugger.h"> RelativePath=".\include\Poco\Debugger.h">
</File> </File>
<File <File
RelativePath=".\include\Poco\DynamicFactory.h"> RelativePath=".\include\Poco\DynamicFactory.h">
</File> </File>
@ -2132,6 +2131,12 @@
<File <File
RelativePath=".\src\NotificationQueue.cpp"> RelativePath=".\src\NotificationQueue.cpp">
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueue.cpp">
</File>
<File
RelativePath=".\src\TimedNotificationQueue.cpp">
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -2154,6 +2159,12 @@
<File <File
RelativePath=".\include\Poco\Observer.h"> RelativePath=".\include\Poco\Observer.h">
</File> </File>
<File
RelativePath=".\include\Poco\PriorityNotificationQueue.h">
</File>
<File
RelativePath=".\include\Poco\TimedNotificationQueue.h">
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
@ -3636,51 +3647,38 @@
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
Name="Dynamic" Name="Dynamic">
>
<Filter <Filter
Name="Header Files" Name="Header Files">
>
<File <File
RelativePath=".\include\Poco\DynamicAny.h" RelativePath=".\include\Poco\DynamicAny.h">
>
</File> </File>
<File <File
RelativePath=".\include\Poco\DynamicAnyHolder.h" RelativePath=".\include\Poco\DynamicAnyHolder.h">
>
</File> </File>
<File <File
RelativePath=".\include\Poco\DynamicStruct.h" RelativePath=".\include\Poco\DynamicStruct.h">
>
</File> </File>
<File <File
RelativePath=".\include\Poco\Dynamic\Pair.h" RelativePath=".\include\Poco\Dynamic\Pair.h">
>
</File>
<File
RelativePath=".\include\Poco\Dynamic\Struct.h"
>
</File> </File>
<File <File
RelativePath=".\include\Poco\Dynamic\Var.h" RelativePath=".\include\Poco\Dynamic\Struct.h">
>
</File> </File>
<File <File
RelativePath=".\include\Poco\Dynamic\VarHolder.h" RelativePath=".\include\Poco\Dynamic\Var.h">
> </File>
<File
RelativePath=".\include\Poco\Dynamic\VarHolder.h">
</File> </File>
</Filter> </Filter>
<Filter <Filter
Name="Source Files" Name="Source Files">
>
<File <File
RelativePath=".\src\Var.cpp" RelativePath=".\src\Var.cpp">
>
</File> </File>
<File <File
RelativePath=".\src\VarHolder.cpp" RelativePath=".\src\VarHolder.cpp">
>
</File> </File>
</Filter> </Filter>
</Filter> </Filter>

View File

@ -2761,6 +2761,14 @@
RelativePath=".\src\NotificationQueue.cpp" RelativePath=".\src\NotificationQueue.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueue.cpp"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueue.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -2789,6 +2797,14 @@
RelativePath=".\include\Poco\Observer.h" RelativePath=".\include\Poco\Observer.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PriorityNotificationQueue.h"
>
</File>
<File
RelativePath=".\include\Poco\TimedNotificationQueue.h"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -2752,6 +2752,14 @@
RelativePath=".\src\NotificationQueue.cpp" RelativePath=".\src\NotificationQueue.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueue.cpp"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueue.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -2780,6 +2788,14 @@
RelativePath=".\include\Poco\Observer.h" RelativePath=".\include\Poco\Observer.h"
> >
</File> </File>
<File
RelativePath=".\include\Poco\PriorityNotificationQueue.h"
>
</File>
<File
RelativePath=".\include\Poco\TimedNotificationQueue.h"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -1,7 +1,7 @@
// //
// File.h // File.h
// //
// $Id: //poco/1.3/Foundation/include/Poco/File.h#6 $ // $Id: //poco/Main/Foundation/include/Poco/File.h#9 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -129,6 +129,9 @@ public:
bool isDirectory() const; bool isDirectory() const;
/// Returns true iff the file is a directory. /// Returns true iff the file is a directory.
bool isDevice() const;
/// Returns true iff the file is a device.
bool isHidden() const; bool isHidden() const;
/// Returns true if the file is hidden. /// Returns true if the file is hidden.

View File

@ -1,7 +1,7 @@
// //
// File_UNIX.h // File_UNIX.h
// //
// $Id: //poco/svn/Foundation/include/Poco/File_UNIX.h#3 $ // $Id: //poco/Main/Foundation/include/Poco/File_UNIX.h#6 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -64,6 +64,7 @@ protected:
bool isFileImpl() const; bool isFileImpl() const;
bool isDirectoryImpl() const; bool isDirectoryImpl() const;
bool isLinkImpl() const; bool isLinkImpl() const;
bool isDeviceImpl() const;
bool isHiddenImpl() const; bool isHiddenImpl() const;
Timestamp createdImpl() const; Timestamp createdImpl() const;
Timestamp getLastModifiedImpl() const; Timestamp getLastModifiedImpl() const;

View File

@ -1,7 +1,7 @@
// //
// File_VMS.h // File_VMS.h
// //
// $Id: //poco/svn/Foundation/include/Poco/File_VMS.h#3 $ // $Id: //poco/Main/Foundation/include/Poco/File_VMS.h#6 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -65,6 +65,7 @@ protected:
bool isFileImpl() const; bool isFileImpl() const;
bool isDirectoryImpl() const; bool isDirectoryImpl() const;
bool isLinkImpl() const; bool isLinkImpl() const;
bool isDeviceImpl() const;
bool isHiddenImpl() const; bool isHiddenImpl() const;
Timestamp createdImpl() const; Timestamp createdImpl() const;
Timestamp getLastModifiedImpl() const; Timestamp getLastModifiedImpl() const;

View File

@ -1,7 +1,7 @@
// //
// File_WIN32.h // File_WIN32.h
// //
// $Id: //poco/svn/Foundation/include/Poco/File_WIN32.h#3 $ // $Id: //poco/Main/Foundation/include/Poco/File_WIN32.h#6 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -65,6 +65,7 @@ protected:
bool isFileImpl() const; bool isFileImpl() const;
bool isDirectoryImpl() const; bool isDirectoryImpl() const;
bool isLinkImpl() const; bool isLinkImpl() const;
bool isDeviceImpl() const;
bool isHiddenImpl() const; bool isHiddenImpl() const;
Timestamp createdImpl() const; Timestamp createdImpl() const;
Timestamp getLastModifiedImpl() const; Timestamp getLastModifiedImpl() const;

View File

@ -1,7 +1,7 @@
// //
// File_WIN32U.h // File_WIN32U.h
// //
// $Id: //poco/svn/Foundation/include/Poco/File_WIN32U.h#3 $ // $Id: //poco/Main/Foundation/include/Poco/File_WIN32U.h#6 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -65,6 +65,7 @@ protected:
bool isFileImpl() const; bool isFileImpl() const;
bool isDirectoryImpl() const; bool isDirectoryImpl() const;
bool isLinkImpl() const; bool isLinkImpl() const;
bool isDeviceImpl() const;
bool isHiddenImpl() const; bool isHiddenImpl() const;
Timestamp createdImpl() const; Timestamp createdImpl() const;
Timestamp getLastModifiedImpl() const; Timestamp getLastModifiedImpl() const;

View File

@ -1,7 +1,7 @@
// //
// NObserver.h // NObserver.h
// //
// $Id: //poco/svn/Foundation/include/Poco/NObserver.h#2 $ // $Id: //poco/Main/Foundation/include/Poco/NObserver.h#2 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -42,7 +42,6 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/AbstractObserver.h" #include "Poco/AbstractObserver.h"
#include "Poco/AutoPtr.h"
namespace Poco { namespace Poco {
@ -65,7 +64,7 @@ class NObserver: public AbstractObserver
/// management. /// management.
{ {
public: public:
typedef AutoPtr<N> NotificationPtr; typedef Notification::Ptr NotificationPtr;
typedef void (C::*Callback)(const NotificationPtr&); typedef void (C::*Callback)(const NotificationPtr&);
NObserver(C& object, Callback method): NObserver(C& object, Callback method):

View File

@ -1,7 +1,7 @@
// //
// Notification.h // Notification.h
// //
// $Id: //poco/svn/Foundation/include/Poco/Notification.h#2 $ // $Id: //poco/Main/Foundation/include/Poco/Notification.h#3 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -43,6 +43,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#include "Poco/RefCountedObject.h" #include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
namespace Poco { namespace Poco {
@ -56,6 +57,8 @@ class Foundation_API Notification: public RefCountedObject
/// template class. /// template class.
{ {
public: public:
typedef AutoPtr<Notification> Ptr;
Notification(); Notification();
/// Creates the notification. /// Creates the notification.

View File

@ -1,7 +1,7 @@
// //
// NotificationCenter.h // NotificationCenter.h
// //
// $Id: //poco/svn/Foundation/include/Poco/NotificationCenter.h#2 $ // $Id: //poco/Main/Foundation/include/Poco/NotificationCenter.h#4 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -41,6 +41,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Notification.h"
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#include <list> #include <list>
@ -48,7 +49,6 @@
namespace Poco { namespace Poco {
class Notification;
class AbstractObserver; class AbstractObserver;
@ -116,7 +116,7 @@ public:
void removeObserver(const AbstractObserver& observer); void removeObserver(const AbstractObserver& observer);
/// Unregisters an observer with the NotificationCenter. /// Unregisters an observer with the NotificationCenter.
void postNotification(Notification* pNotification); void postNotification(Notification::Ptr pNotification);
/// Posts a notification to the NotificationCenter. /// Posts a notification to the NotificationCenter.
/// The NotificationCenter then delivers the notification /// The NotificationCenter then delivers the notification
/// to all interested observers. /// to all interested observers.

View File

@ -1,7 +1,7 @@
// //
// NotificationQueue.h // NotificationQueue.h
// //
// $Id: //poco/svn/Foundation/include/Poco/NotificationQueue.h#2 $ // $Id: //poco/Main/Foundation/include/Poco/NotificationQueue.h#3 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -41,6 +41,7 @@
#include "Poco/Foundation.h" #include "Poco/Foundation.h"
#include "Poco/Notification.h"
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#include "Poco/Event.h" #include "Poco/Event.h"
#include <deque> #include <deque>
@ -49,7 +50,6 @@
namespace Poco { namespace Poco {
class Notification;
class NotificationCenter; class NotificationCenter;
@ -77,7 +77,7 @@ public:
~NotificationQueue(); ~NotificationQueue();
/// Destroys the NotificationQueue. /// Destroys the NotificationQueue.
void enqueueNotification(Notification* pNotification); void enqueueNotification(Notification::Ptr pNotification);
/// Enqueues the given notification by adding it to /// Enqueues the given notification by adding it to
/// the end of the queue (FIFO). /// the end of the queue (FIFO).
/// The queue takes ownership of the notification, thus /// The queue takes ownership of the notification, thus
@ -85,7 +85,7 @@ public:
/// notificationQueue.enqueueNotification(new MyNotification); /// notificationQueue.enqueueNotification(new MyNotification);
/// does not result in a memory leak. /// does not result in a memory leak.
void enqueueUrgentNotification(Notification* pNotification); void enqueueUrgentNotification(Notification::Ptr pNotification);
/// Enqueues the given notification by adding it to /// Enqueues the given notification by adding it to
/// the front of the queue (LIFO). The event therefore gets processed /// the front of the queue (LIFO). The event therefore gets processed
/// before all other events already in the queue. /// before all other events already in the queue.
@ -99,6 +99,10 @@ public:
/// Returns 0 (null) if no notification is available. /// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and /// The caller gains ownership of the notification and
/// is expected to release it when done with it. /// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification(); Notification* waitDequeueNotification();
/// Dequeues the next pending notification. /// Dequeues the next pending notification.
@ -108,6 +112,10 @@ public:
/// is expected to release it when done with it. /// is expected to release it when done with it.
/// This method returns 0 (null) if wakeUpWaitingThreads() /// This method returns 0 (null) if wakeUpWaitingThreads()
/// has been called by another thread. /// has been called by another thread.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification(long milliseconds); Notification* waitDequeueNotification(long milliseconds);
/// Dequeues the next pending notification. /// Dequeues the next pending notification.
@ -116,6 +124,10 @@ public:
/// Returns 0 (null) if no notification is available. /// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and /// The caller gains ownership of the notification and
/// is expected to release it when done with it. /// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
void dispatch(NotificationCenter& notificationCenter); void dispatch(NotificationCenter& notificationCenter);
/// Dispatches all queued notifications to the given /// Dispatches all queued notifications to the given
@ -142,14 +154,14 @@ public:
/// NotificationQueue. /// NotificationQueue.
protected: protected:
Notification* dequeueOne(); Notification::Ptr dequeueOne();
private: private:
typedef std::deque<Notification*> NfQueue; typedef std::deque<Notification::Ptr> NfQueue;
struct WaitInfo struct WaitInfo
{ {
Notification* pNf; Notification::Ptr pNf;
Event nfAvailable; Event nfAvailable;
}; };
typedef std::deque<WaitInfo*> WaitQueue; typedef std::deque<WaitInfo*> WaitQueue;

View File

@ -0,0 +1,180 @@
//
// PriorityNotificationQueue.h
//
// $Id: //poco/Main/Foundation/include/Poco/PriorityNotificationQueue.h#1 $
//
// Library: Foundation
// Package: Notifications
// Module: PriorityNotificationQueue
//
// Definition of the PriorityNotificationQueue class.
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef Foundation_PriorityNotificationQueue_INCLUDED
#define Foundation_PriorityNotificationQueue_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/Notification.h"
#include "Poco/Mutex.h"
#include "Poco/Event.h"
#include <map>
#include <deque>
namespace Poco {
class NotificationCenter;
class Foundation_API PriorityNotificationQueue
/// A PriorityNotificationQueue object provides a way to implement asynchronous
/// notifications. This is especially useful for sending notifications
/// from one thread to another, for example from a background thread to
/// the main (user interface) thread.
///
/// The PriorityNotificationQueue is quite similar to the NotificationQueue class.
/// The only difference to NotificationQueue is that each Notification is tagged
/// with a priority value. When inserting a Notification into the queue, the
/// Notification is inserted according to the given priority value, with
/// lower priority values being inserted before higher priority
/// values. Therefore, the lower the numerical priority value, the higher
/// the actual notification priority.
///
/// Notifications are dequeued in order of their priority.
///
/// The PriorityNotificationQueue can also be used to distribute work from
/// a controlling thread to one or more worker threads. Each worker thread
/// repeatedly calls waitDequeueNotification() and processes the
/// returned notification. Special care must be taken when shutting
/// down a queue with worker threads waiting for notifications.
/// The recommended sequence to shut down and destroy the queue is to
/// 1. set a termination flag for every worker thread
/// 2. call the wakeUpAll() method
/// 3. join each worker thread
/// 4. destroy the notification queue.
{
public:
PriorityNotificationQueue();
/// Creates the PriorityNotificationQueue.
~PriorityNotificationQueue();
/// Destroys the PriorityNotificationQueue.
void enqueueNotification(Notification::Ptr pNotification, int priority);
/// Enqueues the given notification by adding it to
/// the queue according to the given priority.
/// Lower priority values are inserted before higher priority values.
/// The queue takes ownership of the notification, thus
/// a call like
/// notificationQueue.enqueueNotification(new MyNotification, 1);
/// does not result in a memory leak.
Notification* dequeueNotification();
/// Dequeues the next pending notification.
/// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification();
/// Dequeues the next pending notification.
/// If no notification is available, waits for a notification
/// to be enqueued.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
/// This method returns 0 (null) if wakeUpWaitingThreads()
/// has been called by another thread.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification(long milliseconds);
/// Dequeues the next pending notification.
/// If no notification is available, waits for a notification
/// to be enqueued up to the specified time.
/// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
void dispatch(NotificationCenter& notificationCenter);
/// Dispatches all queued notifications to the given
/// notification center.
void wakeUpAll();
/// Wakes up all threads that wait for a notification.
bool empty() const;
/// Returns true iff the queue is empty.
int size() const;
/// Returns the number of notifications in the queue.
void clear();
/// Removes all notifications from the queue.
bool hasIdleThreads() const;
/// Returns true if the queue has at least one thread waiting
/// for a notification.
static PriorityNotificationQueue& defaultQueue();
/// Returns a reference to the default
/// PriorityNotificationQueue.
protected:
Notification::Ptr dequeueOne();
private:
typedef std::multimap<int, Notification::Ptr> NfQueue;
struct WaitInfo
{
Notification::Ptr pNf;
Event nfAvailable;
};
typedef std::deque<WaitInfo*> WaitQueue;
NfQueue _nfQueue;
WaitQueue _waitQueue;
mutable FastMutex _mutex;
};
} // namespace Poco
#endif // Foundation_PriorityNotificationQueue_INCLUDED

View File

@ -0,0 +1,155 @@
//
// TimedNotificationQueue.h
//
// $Id: //poco/Main/Foundation/include/Poco/TimedNotificationQueue.h#1 $
//
// Library: Foundation
// Package: Notifications
// Module: TimedNotificationQueue
//
// Definition of the TimedNotificationQueue class.
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef Foundation_TimedNotificationQueue_INCLUDED
#define Foundation_TimedNotificationQueue_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/Notification.h"
#include "Poco/Mutex.h"
#include "Poco/Event.h"
#include "Poco/Timestamp.h"
#include <map>
namespace Poco {
class Foundation_API TimedNotificationQueue
/// A TimedNotificationQueue object provides a way to implement timed, asynchronous
/// notifications. This is especially useful for sending notifications
/// from one thread to another, for example from a background thread to
/// the main (user interface) thread.
///
/// The TimedNotificationQueue is quite similar to the NotificationQueue class.
/// The only difference to NotificationQueue is that each Notification is tagged
/// with a Timestamp. When inserting a Notification into the queue, the
/// Notification is inserted according to the given Timestamp, with
/// lower Timestamp values being inserted before higher ones.
///
/// Notifications are dequeued in order of their timestamps.
///
/// TimedNotificationQueue has some restrictions regarding multithreaded use.
/// While multiple threads may enqueue notifications, only one thread at a
/// time may dequeue notifications from the queue.
///
/// If two threads try to dequeue a notification simultaneously, the results
/// are undefined.
{
public:
TimedNotificationQueue();
/// Creates the TimedNotificationQueue.
~TimedNotificationQueue();
/// Destroys the TimedNotificationQueue.
void enqueueNotification(Notification::Ptr pNotification, Timestamp timestamp);
/// Enqueues the given notification by adding it to
/// the queue according to the given timestamp.
/// Lower timestamp values are inserted before higher ones.
/// The queue takes ownership of the notification, thus
/// a call like
/// notificationQueue.enqueueNotification(new MyNotification, someTime);
/// does not result in a memory leak.
Notification* dequeueNotification();
/// Dequeues the next pending notification with a timestamp
/// less than or equal to the current time.
/// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification();
/// Dequeues the next pending notification.
/// If no notification is available, waits for a notification
/// to be enqueued.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
/// This method returns 0 (null) if wakeUpWaitingThreads()
/// has been called by another thread.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
Notification* waitDequeueNotification(long milliseconds);
/// Dequeues the next pending notification.
/// If no notification is available, waits for a notification
/// to be enqueued up to the specified time.
/// Returns 0 (null) if no notification is available.
/// The caller gains ownership of the notification and
/// is expected to release it when done with it.
///
/// It is highly recommended that the result is immediately
/// assigned to a Notification::Ptr, to avoid potential
/// memory management issues.
bool empty() const;
/// Returns true iff the queue is empty.
int size() const;
/// Returns the number of notifications in the queue.
void clear();
/// Removes all notifications from the queue.
///
/// Calling clear() while another thread executes one of
/// the dequeue member functions will result in undefined
/// behavior.
protected:
typedef std::multimap<Timestamp, Notification::Ptr> NfQueue;
Notification::Ptr dequeueOne(NfQueue::iterator& it);
bool wait(Timestamp::TimeDiff interval);
private:
NfQueue _nfQueue;
Event _nfAvailable;
mutable FastMutex _mutex;
};
} // namespace Poco
#endif // Foundation_TimedNotificationQueue_INCLUDED

View File

@ -1,7 +1,7 @@
// //
// Timer.h // Timer.h
// //
// $Id: //poco/svn/Foundation/include/Poco/Timer.h#3 $ // $Id: //poco/Main/Foundation/include/Poco/Timer.h#5 $
// //
// Library: Foundation // Library: Foundation
// Package: Threading // Package: Threading
@ -45,6 +45,7 @@
#include "Poco/Mutex.h" #include "Poco/Mutex.h"
#include "Poco/Event.h" #include "Poco/Event.h"
#include "Poco/Thread.h" #include "Poco/Thread.h"
#include "Poco/Timestamp.h"
namespace Poco { namespace Poco {
@ -71,6 +72,14 @@ class Foundation_API Timer: protected Runnable
/// factors like operating system, CPU performance and system load and /// factors like operating system, CPU performance and system load and
/// may differ from the specified interval. /// may differ from the specified interval.
/// ///
/// The time needed to execute the timer callback is not included
/// in the interval between invocations. For example, if the interval
/// is 500 milliseconds, and the callback needs 400 milliseconds to
/// execute, the callback function is nevertheless called every 500
/// milliseconds. If the callback takes longer to execute than the
/// interval, the callback function will be immediately called again
/// once it returns.
///
/// The timer thread is taken from a thread pool, so /// The timer thread is taken from a thread pool, so
/// there is a limit to the number of available concurrent timers. /// there is a limit to the number of available concurrent timers.
{ {
@ -152,6 +161,7 @@ private:
Event _wakeUp; Event _wakeUp;
Event _done; Event _done;
AbstractTimerCallback* _pCallback; AbstractTimerCallback* _pCallback;
Poco::Timestamp _nextInvocation;
mutable FastMutex _mutex; mutable FastMutex _mutex;
Timer(const Timer&); Timer(const Timer&);

View File

@ -1,7 +1,7 @@
// //
// File.cpp // File.cpp
// //
// $Id: //poco/svn/Foundation/src/File.cpp#3 $ // $Id: //poco/Main/Foundation/src/File.cpp#22 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -160,6 +160,12 @@ bool File::isLink() const
} }
bool File::isDevice() const
{
return isDeviceImpl();
}
bool File::isHidden() const bool File::isHidden() const
{ {
return isHiddenImpl(); return isHiddenImpl();
@ -219,7 +225,7 @@ void File::copyTo(const std::string& path) const
Path src(getPathImpl()); Path src(getPathImpl());
Path dest(path); Path dest(path);
File destFile(path); File destFile(path);
if (destFile.exists() && destFile.isDirectory() || dest.isDirectory()) if ((destFile.exists() && destFile.isDirectory()) || dest.isDirectory())
{ {
dest.makeDirectory(); dest.makeDirectory();
dest.setFileName(src.getFileName()); dest.setFileName(src.getFileName());

View File

@ -1,7 +1,7 @@
// //
// File_UNIX.cpp // File_UNIX.cpp
// //
// $Id: //poco/1.3/Foundation/src/File_UNIX.cpp#12 $ // $Id: //poco/Main/Foundation/src/File_UNIX.cpp#26 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -193,6 +193,19 @@ bool FileImpl::isLinkImpl() const
} }
bool FileImpl::isDeviceImpl() const
{
poco_assert (!_path.empty());
struct stat st;
if (stat(_path.c_str(), &st) == 0)
return S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode);
else
handleLastErrorImpl(_path);
return false;
}
bool FileImpl::isHiddenImpl() const bool FileImpl::isHiddenImpl() const
{ {
poco_assert (!_path.empty()); poco_assert (!_path.empty());
@ -443,8 +456,10 @@ void FileImpl::handleLastErrorImpl(const std::string& path)
throw FileException("no space left on device", path); throw FileException("no space left on device", path);
case EDQUOT: case EDQUOT:
throw FileException("disk quota exceeded", path); throw FileException("disk quota exceeded", path);
#if !defined(_AIX)
case ENOTEMPTY: case ENOTEMPTY:
throw FileException("directory not empty", path); throw FileException("directory not empty", path);
#endif
case ENAMETOOLONG: case ENAMETOOLONG:
throw PathSyntaxException(path); throw PathSyntaxException(path);
case ENFILE: case ENFILE:

View File

@ -1,7 +1,7 @@
// //
// File_VMS.cpp // File_VMS.cpp
// //
// $Id: //poco/1.3/Foundation/src/File_VMS.cpp#4 $ // $Id: //poco/Main/Foundation/src/File_VMS.cpp#18 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -174,6 +174,12 @@ bool FileImpl::isLinkImpl() const
} }
bool FileImpl::isLinkImpl() const
{
return false;
}
bool FileImpl::isHiddenImpl() const bool FileImpl::isHiddenImpl() const
{ {
return false; return false;

View File

@ -1,7 +1,7 @@
// //
// File_WIN32.cpp // File_WIN32.cpp
// //
// $Id: //poco/1.3/Foundation/src/File_WIN32.cpp#8 $ // $Id: //poco/Main/Foundation/src/File_WIN32.cpp#24 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -165,12 +165,7 @@ bool FileImpl::canExecuteImpl() const
bool FileImpl::isFileImpl() const bool FileImpl::isFileImpl() const
{ {
poco_assert (!_path.empty()); return !isDirectoryImpl() && !isDeviceImpl();
DWORD attr = GetFileAttributes(_path.c_str());
if (attr == 0xFFFFFFFF)
handleLastErrorImpl(_path);
return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0;
} }
@ -191,6 +186,20 @@ bool FileImpl::isLinkImpl() const
} }
bool FileImpl::isDeviceImpl() const
{
poco_assert (!_path.empty());
FileHandle fh(_path, GENERIC_READ, 0, OPEN_EXISTING);
DWORD type = GetFileType(fh.get());
if (type == FILE_TYPE_CHAR)
return true;
else if (type == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR)
handleLastErrorImpl(_path);
return false;
}
bool FileImpl::isHiddenImpl() const bool FileImpl::isHiddenImpl() const
{ {
poco_assert (!_path.empty()); poco_assert (!_path.empty());
@ -234,7 +243,7 @@ void FileImpl::setLastModifiedImpl(const Timestamp& ts)
FILETIME ft; FILETIME ft;
ft.dwLowDateTime = low; ft.dwLowDateTime = low;
ft.dwHighDateTime = high; ft.dwHighDateTime = high;
FileHandle fh(_path, FILE_ALL_ACCESS, FILE_SHARE_WRITE, OPEN_EXISTING); FileHandle fh(_path, FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
if (SetFileTime(fh.get(), 0, &ft, &ft) == 0) if (SetFileTime(fh.get(), 0, &ft, &ft) == 0)
handleLastErrorImpl(_path); handleLastErrorImpl(_path);
} }
@ -258,7 +267,7 @@ void FileImpl::setSizeImpl(FileSizeImpl size)
{ {
poco_assert (!_path.empty()); poco_assert (!_path.empty());
FileHandle fh(_path, GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING); FileHandle fh(_path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
LARGE_INTEGER li; LARGE_INTEGER li;
li.QuadPart = size; li.QuadPart = size;
if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1) if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1)

View File

@ -1,7 +1,7 @@
// //
// File_WIN32U.cpp // File_WIN32U.cpp
// //
// $Id: //poco/1.3/Foundation/src/File_WIN32U.cpp#8 $ // $Id: //poco/Main/Foundation/src/File_WIN32U.cpp#17 $
// //
// Library: Foundation // Library: Foundation
// Package: Filesystem // Package: Filesystem
@ -169,12 +169,7 @@ bool FileImpl::canExecuteImpl() const
bool FileImpl::isFileImpl() const bool FileImpl::isFileImpl() const
{ {
poco_assert (!_path.empty()); return !isDirectoryImpl() && !isDeviceImpl();
DWORD attr = GetFileAttributesW(_upath.c_str());
if (attr == 0xFFFFFFFF)
handleLastErrorImpl(_path);
return (attr & FILE_ATTRIBUTE_DIRECTORY) == 0;
} }
@ -195,6 +190,20 @@ bool FileImpl::isLinkImpl() const
} }
bool FileImpl::isDeviceImpl() const
{
poco_assert (!_path.empty());
FileHandle fh(_path, _upath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
DWORD type = GetFileType(fh.get());
if (type == FILE_TYPE_CHAR)
return true;
else if (type == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR)
handleLastErrorImpl(_path);
return false;
}
bool FileImpl::isHiddenImpl() const bool FileImpl::isHiddenImpl() const
{ {
poco_assert (!_path.empty()); poco_assert (!_path.empty());
@ -238,7 +247,7 @@ void FileImpl::setLastModifiedImpl(const Timestamp& ts)
FILETIME ft; FILETIME ft;
ft.dwLowDateTime = low; ft.dwLowDateTime = low;
ft.dwHighDateTime = high; ft.dwHighDateTime = high;
FileHandle fh(_path, _upath, FILE_ALL_ACCESS, FILE_SHARE_WRITE, OPEN_EXISTING); FileHandle fh(_path, _upath, FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
if (SetFileTime(fh.get(), 0, &ft, &ft) == 0) if (SetFileTime(fh.get(), 0, &ft, &ft) == 0)
handleLastErrorImpl(_path); handleLastErrorImpl(_path);
} }
@ -262,7 +271,7 @@ void FileImpl::setSizeImpl(FileSizeImpl size)
{ {
poco_assert (!_path.empty()); poco_assert (!_path.empty());
FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_WRITE, OPEN_EXISTING); FileHandle fh(_path, _upath, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
LARGE_INTEGER li; LARGE_INTEGER li;
li.QuadPart = size; li.QuadPart = size;
if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1) if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1)

View File

@ -1,7 +1,7 @@
// //
// NotificationCenter.cpp // NotificationCenter.cpp
// //
// $Id: //poco/svn/Foundation/src/NotificationCenter.cpp#2 $ // $Id: //poco/Main/Foundation/src/NotificationCenter.cpp#13 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -80,12 +80,11 @@ void NotificationCenter::removeObserver(const AbstractObserver& observer)
} }
void NotificationCenter::postNotification(Notification* pNotification) void NotificationCenter::postNotification(Notification::Ptr pNotification)
{ {
poco_check_ptr (pNotification); poco_check_ptr (pNotification);
Mutex::ScopedLock lock(_mutex); Mutex::ScopedLock lock(_mutex);
AutoPtr<Notification> pNf = pNotification;
ObserverList::iterator it = _observers.begin(); ObserverList::iterator it = _observers.begin();
while (it != _observers.end()) while (it != _observers.end())
{ {

View File

@ -1,7 +1,7 @@
// //
// NotificationQueue.cpp // NotificationQueue.cpp
// //
// $Id: //poco/svn/Foundation/src/NotificationQueue.cpp#2 $ // $Id: //poco/Main/Foundation/src/NotificationQueue.cpp#15 $
// //
// Library: Foundation // Library: Foundation
// Package: Notifications // Package: Notifications
@ -54,7 +54,7 @@ NotificationQueue::~NotificationQueue()
} }
void NotificationQueue::enqueueNotification(Notification* pNotification) void NotificationQueue::enqueueNotification(Notification::Ptr pNotification)
{ {
poco_check_ptr (pNotification); poco_check_ptr (pNotification);
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
@ -72,7 +72,7 @@ void NotificationQueue::enqueueNotification(Notification* pNotification)
} }
void NotificationQueue::enqueueUrgentNotification(Notification* pNotification) void NotificationQueue::enqueueUrgentNotification(Notification::Ptr pNotification)
{ {
poco_check_ptr (pNotification); poco_check_ptr (pNotification);
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
@ -93,39 +93,37 @@ void NotificationQueue::enqueueUrgentNotification(Notification* pNotification)
Notification* NotificationQueue::dequeueNotification() Notification* NotificationQueue::dequeueNotification()
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
return dequeueOne(); return dequeueOne().duplicate();
} }
Notification* NotificationQueue::waitDequeueNotification() Notification* NotificationQueue::waitDequeueNotification()
{ {
Notification* pNf = 0; Notification::Ptr pNf;
WaitInfo* pWI = 0; WaitInfo* pWI = 0;
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
pNf = dequeueOne(); pNf = dequeueOne();
if (pNf) return pNf; if (pNf) return pNf.duplicate();
pWI = new WaitInfo; pWI = new WaitInfo;
pWI->pNf = 0;
_waitQueue.push_back(pWI); _waitQueue.push_back(pWI);
} }
pWI->nfAvailable.wait(); pWI->nfAvailable.wait();
pNf = pWI->pNf; pNf = pWI->pNf;
delete pWI; delete pWI;
return pNf; return pNf.duplicate();
} }
Notification* NotificationQueue::waitDequeueNotification(long milliseconds) Notification* NotificationQueue::waitDequeueNotification(long milliseconds)
{ {
Notification* pNf = 0; Notification::Ptr pNf;
WaitInfo* pWI = 0; WaitInfo* pWI = 0;
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
pNf = dequeueOne(); pNf = dequeueOne();
if (pNf) return pNf; if (pNf) return pNf.duplicate();
pWI = new WaitInfo; pWI = new WaitInfo;
pWI->pNf = 0;
_waitQueue.push_back(pWI); _waitQueue.push_back(pWI);
} }
if (pWI->nfAvailable.tryWait(milliseconds)) if (pWI->nfAvailable.tryWait(milliseconds))
@ -146,14 +144,14 @@ Notification* NotificationQueue::waitDequeueNotification(long milliseconds)
} }
} }
delete pWI; delete pWI;
return pNf; return pNf.duplicate();
} }
void NotificationQueue::dispatch(NotificationCenter& notificationCenter) void NotificationQueue::dispatch(NotificationCenter& notificationCenter)
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
Notification* pNf = dequeueOne(); Notification::Ptr pNf = dequeueOne();
while (pNf) while (pNf)
{ {
notificationCenter.postNotification(pNf); notificationCenter.postNotification(pNf);
@ -183,17 +181,13 @@ bool NotificationQueue::empty() const
int NotificationQueue::size() const int NotificationQueue::size() const
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
return int(_nfQueue.size()); return static_cast<int>(_nfQueue.size());
} }
void NotificationQueue::clear() void NotificationQueue::clear()
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
for (NfQueue::iterator it = _nfQueue.begin(); it != _nfQueue.end(); ++it)
{
(*it)->release();
}
_nfQueue.clear(); _nfQueue.clear();
} }
@ -205,9 +199,9 @@ bool NotificationQueue::hasIdleThreads() const
} }
Notification* NotificationQueue::dequeueOne() Notification::Ptr NotificationQueue::dequeueOne()
{ {
Notification* pNf = 0; Notification::Ptr pNf;
if (!_nfQueue.empty()) if (!_nfQueue.empty())
{ {
pNf = _nfQueue.front(); pNf = _nfQueue.front();

View File

@ -0,0 +1,205 @@
//
// PriorityNotificationQueue.cpp
//
// $Id: //poco/Main/Foundation/src/PriorityNotificationQueue.cpp#1 $
//
// Library: Foundation
// Package: Notifications
// Module: PriorityNotificationQueue
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/PriorityNotificationQueue.h"
#include "Poco/NotificationCenter.h"
#include "Poco/Notification.h"
#include "Poco/SingletonHolder.h"
namespace Poco {
PriorityNotificationQueue::PriorityNotificationQueue()
{
}
PriorityNotificationQueue::~PriorityNotificationQueue()
{
clear();
}
void PriorityNotificationQueue::enqueueNotification(Notification::Ptr pNotification, int priority)
{
poco_check_ptr (pNotification);
FastMutex::ScopedLock lock(_mutex);
if (_waitQueue.empty())
{
_nfQueue.insert(NfQueue::value_type(priority, pNotification));
}
else
{
poco_assert_dbg(_nfQueue.empty());
WaitInfo* pWI = _waitQueue.front();
_waitQueue.pop_front();
pWI->pNf = pNotification;
pWI->nfAvailable.set();
}
}
Notification* PriorityNotificationQueue::dequeueNotification()
{
FastMutex::ScopedLock lock(_mutex);
return dequeueOne().duplicate();
}
Notification* PriorityNotificationQueue::waitDequeueNotification()
{
Notification::Ptr pNf;
WaitInfo* pWI = 0;
{
FastMutex::ScopedLock lock(_mutex);
pNf = dequeueOne();
if (pNf) return pNf.duplicate();
pWI = new WaitInfo;
_waitQueue.push_back(pWI);
}
pWI->nfAvailable.wait();
pNf = pWI->pNf;
delete pWI;
return pNf.duplicate();
}
Notification* PriorityNotificationQueue::waitDequeueNotification(long milliseconds)
{
Notification::Ptr pNf;
WaitInfo* pWI = 0;
{
FastMutex::ScopedLock lock(_mutex);
pNf = dequeueOne();
if (pNf) return pNf.duplicate();
pWI = new WaitInfo;
_waitQueue.push_back(pWI);
}
if (pWI->nfAvailable.tryWait(milliseconds))
{
pNf = pWI->pNf;
}
else
{
FastMutex::ScopedLock lock(_mutex);
pNf = pWI->pNf;
for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it)
{
if (*it == pWI)
{
_waitQueue.erase(it);
break;
}
}
}
delete pWI;
return pNf.duplicate();
}
void PriorityNotificationQueue::dispatch(NotificationCenter& notificationCenter)
{
FastMutex::ScopedLock lock(_mutex);
Notification::Ptr pNf = dequeueOne();
while (pNf)
{
notificationCenter.postNotification(pNf);
pNf = dequeueOne();
}
}
void PriorityNotificationQueue::wakeUpAll()
{
FastMutex::ScopedLock lock(_mutex);
for (WaitQueue::iterator it = _waitQueue.begin(); it != _waitQueue.end(); ++it)
{
(*it)->nfAvailable.set();
}
_waitQueue.clear();
}
bool PriorityNotificationQueue::empty() const
{
FastMutex::ScopedLock lock(_mutex);
return _nfQueue.empty();
}
int PriorityNotificationQueue::size() const
{
FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_nfQueue.size());
}
void PriorityNotificationQueue::clear()
{
FastMutex::ScopedLock lock(_mutex);
_nfQueue.clear();
}
bool PriorityNotificationQueue::hasIdleThreads() const
{
FastMutex::ScopedLock lock(_mutex);
return !_waitQueue.empty();
}
Notification::Ptr PriorityNotificationQueue::dequeueOne()
{
Notification::Ptr pNf;
NfQueue::iterator it = _nfQueue.begin();
if (it != _nfQueue.end())
{
pNf = it->second;
_nfQueue.erase(it);
}
return pNf;
}
PriorityNotificationQueue& PriorityNotificationQueue::defaultQueue()
{
static SingletonHolder<PriorityNotificationQueue> sh;
return *sh.get();
}
} // namespace Poco

View File

@ -0,0 +1,203 @@
//
// TimedNotificationQueue.cpp
//
// $Id: //poco/Main/Foundation/src/TimedNotificationQueue.cpp#1 $
//
// Library: Foundation
// Package: Notifications
// Module: TimedNotificationQueue
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/TimedNotificationQueue.h"
#include "Poco/Notification.h"
#include <limits>
namespace Poco {
TimedNotificationQueue::TimedNotificationQueue()
{
}
TimedNotificationQueue::~TimedNotificationQueue()
{
clear();
}
void TimedNotificationQueue::enqueueNotification(Notification::Ptr pNotification, Timestamp timestamp)
{
poco_check_ptr (pNotification);
FastMutex::ScopedLock lock(_mutex);
_nfQueue.insert(NfQueue::value_type(timestamp, pNotification));
_nfAvailable.set();
}
Notification* TimedNotificationQueue::dequeueNotification()
{
FastMutex::ScopedLock lock(_mutex);
NfQueue::iterator it = _nfQueue.begin();
if (it != _nfQueue.end())
{
Timestamp::TimeDiff sleep = -it->first.elapsed();
if (sleep <= 0)
{
Notification::Ptr pNf = it->second;
_nfQueue.erase(it);
return pNf.duplicate();
}
}
return 0;
}
Notification* TimedNotificationQueue::waitDequeueNotification()
{
for (;;)
{
_mutex.lock();
NfQueue::iterator it = _nfQueue.begin();
if (it != _nfQueue.end())
{
_mutex.unlock();
Timestamp::TimeDiff sleep = -it->first.elapsed();
if (sleep <= 0)
{
return dequeueOne(it).duplicate();
}
else if (!wait(sleep))
{
return dequeueOne(it).duplicate();
}
else continue;
}
else
{
_mutex.unlock();
}
_nfAvailable.wait();
}
}
Notification* TimedNotificationQueue::waitDequeueNotification(long milliseconds)
{
while (milliseconds >= 0)
{
_mutex.lock();
NfQueue::iterator it = _nfQueue.begin();
if (it != _nfQueue.end())
{
_mutex.unlock();
Poco::Timestamp now;
Timestamp::TimeDiff sleep = it->first - now;
if (sleep <= 0)
{
return dequeueOne(it).duplicate();
}
else if (sleep <= 1000*Timestamp::TimeDiff(milliseconds))
{
if (!wait(sleep))
{
return dequeueOne(it).duplicate();
}
else
{
milliseconds -= static_cast<long>((now.elapsed() + 999)/1000);
continue;
}
}
}
else
{
_mutex.unlock();
}
if (milliseconds > 0)
{
Poco::Timestamp now;
_nfAvailable.tryWait(milliseconds);
milliseconds -= static_cast<long>((now.elapsed() + 999)/1000);
}
else return 0;
}
return 0;
}
bool TimedNotificationQueue::wait(Timestamp::TimeDiff interval)
{
const Timestamp::TimeDiff MAX_SLEEP = 8*60*60*Timestamp::TimeDiff(1000000); // sleep at most 8 hours at a time
while (interval > 0)
{
Timestamp now;
Timestamp::TimeDiff sleep = interval <= MAX_SLEEP ? interval : MAX_SLEEP;
if (_nfAvailable.tryWait(static_cast<long>((interval + 999)/1000)))
return true;
interval -= now.elapsed();
}
return false;
}
bool TimedNotificationQueue::empty() const
{
FastMutex::ScopedLock lock(_mutex);
return _nfQueue.empty();
}
int TimedNotificationQueue::size() const
{
FastMutex::ScopedLock lock(_mutex);
return static_cast<int>(_nfQueue.size());
}
void TimedNotificationQueue::clear()
{
FastMutex::ScopedLock lock(_mutex);
_nfQueue.clear();
}
Notification::Ptr TimedNotificationQueue::dequeueOne(NfQueue::iterator& it)
{
FastMutex::ScopedLock lock(_mutex);
Notification::Ptr pNf = it->second;
_nfQueue.erase(it);
return pNf;
}
} // namespace Poco

View File

@ -1,7 +1,7 @@
// //
// Timer.cpp // Timer.cpp
// //
// $Id: //poco/svn/Foundation/src/Timer.cpp#3 $ // $Id: //poco/Main/Foundation/src/Timer.cpp#14 $
// //
// Library: Foundation // Library: Foundation
// Package: Threading // Package: Threading
@ -78,9 +78,13 @@ void Timer::start(const AbstractTimerCallback& method, ThreadPool& threadPool)
void Timer::start(const AbstractTimerCallback& method, Thread::Priority priority, ThreadPool& threadPool) void Timer::start(const AbstractTimerCallback& method, Thread::Priority priority, ThreadPool& threadPool)
{ {
Poco::Timestamp nextInvocation;
nextInvocation += _startInterval*1000;
poco_assert (!_pCallback); poco_assert (!_pCallback);
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
_nextInvocation = nextInvocation;
_pCallback = method.clone(); _pCallback = method.clone();
_wakeUp.reset(); _wakeUp.reset();
threadPool.startWithPriority(priority, *this); threadPool.startWithPriority(priority, *this);
@ -157,14 +161,14 @@ void Timer::setPeriodicInterval(long milliseconds)
void Timer::run() void Timer::run()
{ {
long interval; Poco::Timestamp now;
{ long interval(0);
FastMutex::ScopedLock lock(_mutex);
interval = _startInterval;
}
do do
{ {
if (_wakeUp.tryWait(interval)) now.update();
long sleep = static_cast<long>((_nextInvocation - now)/1000);
if (sleep < 0) sleep = 0;
if (_wakeUp.tryWait(sleep))
{ {
FastMutex::ScopedLock lock(_mutex); FastMutex::ScopedLock lock(_mutex);
interval = _periodicInterval; interval = _periodicInterval;
@ -192,6 +196,7 @@ void Timer::run()
interval = _periodicInterval; interval = _periodicInterval;
} }
} }
_nextInvocation += interval*1000;
} }
while (interval > 0); while (interval > 0);
_done.set(); _done.set();

View File

@ -553,6 +553,12 @@
<File <File
RelativePath=".\src\NotificationsTestSuite.cpp"> RelativePath=".\src\NotificationsTestSuite.cpp">
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.cpp">
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.cpp">
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -566,6 +572,12 @@
<File <File
RelativePath=".\src\NotificationsTestSuite.h"> RelativePath=".\src\NotificationsTestSuite.h">
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.h">
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.h">
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
@ -1210,30 +1222,23 @@
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
Name="Dynamic" Name="Dynamic">
>
<Filter <Filter
Name="Header Files" Name="Header Files">
>
<File <File
RelativePath=".\src\DynamicTestSuite.h" RelativePath=".\src\DynamicTestSuite.h">
>
</File> </File>
<File <File
RelativePath=".\src\VarTest.h" RelativePath=".\src\VarTest.h">
>
</File> </File>
</Filter> </Filter>
<Filter <Filter
Name="Source Files" Name="Source Files">
>
<File <File
RelativePath=".\src\DynamicTestSuite.cpp" RelativePath=".\src\DynamicTestSuite.cpp">
>
</File> </File>
<File <File
RelativePath=".\src\VarTest.cpp" RelativePath=".\src\VarTest.cpp">
>
</File> </File>
</Filter> </Filter>
</Filter> </Filter>

View File

@ -762,6 +762,14 @@
RelativePath=".\src\NotificationsTestSuite.cpp" RelativePath=".\src\NotificationsTestSuite.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.cpp"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -778,6 +786,14 @@
RelativePath=".\src\NotificationsTestSuite.h" RelativePath=".\src\NotificationsTestSuite.h"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.h"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.h"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -751,6 +751,14 @@
RelativePath=".\src\NotificationsTestSuite.cpp" RelativePath=".\src\NotificationsTestSuite.cpp"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.cpp"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
@ -767,6 +775,14 @@
RelativePath=".\src\NotificationsTestSuite.h" RelativePath=".\src\NotificationsTestSuite.h"
> >
</File> </File>
<File
RelativePath=".\src\PriorityNotificationQueueTest.h"
>
</File>
<File
RelativePath=".\src\TimedNotificationQueueTest.h"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -1,7 +1,7 @@
// //
// FileTest.cpp // FileTest.cpp
// //
// $Id: //poco/svn/Foundation/testsuite/src/FileTest.cpp#3 $ // $Id: //poco/Main/Foundation/testsuite/src/FileTest.cpp#16 $
// //
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@ -245,6 +245,21 @@ void FileTest::testFileAttributes2()
} }
void FileTest::testFileAttributes3()
{
#if defined(POCO_OS_FAMILY_UNIX)
File f("/dev/console");
#elif defined(POCO_OS_FAMILY_WINDOWS)
File f("CON");
#endif
assert (f.isDevice());
assert (!f.isFile());
assert (!f.isDirectory());
assert (!f.isLink());
}
void FileTest::testCompare() void FileTest::testCompare()
{ {
File f1("abc.txt"); File f1("abc.txt");
@ -511,6 +526,7 @@ CppUnit::Test* FileTest::suite()
CppUnit_addTest(pSuite, FileTest, testFileAttributes1); CppUnit_addTest(pSuite, FileTest, testFileAttributes1);
CppUnit_addTest(pSuite, FileTest, testFileAttributes2); CppUnit_addTest(pSuite, FileTest, testFileAttributes2);
CppUnit_addTest(pSuite, FileTest, testFileAttributes3);
CppUnit_addTest(pSuite, FileTest, testCompare); CppUnit_addTest(pSuite, FileTest, testCompare);
CppUnit_addTest(pSuite, FileTest, testSwap); CppUnit_addTest(pSuite, FileTest, testSwap);
CppUnit_addTest(pSuite, FileTest, testSize); CppUnit_addTest(pSuite, FileTest, testSize);

View File

@ -1,7 +1,7 @@
// //
// FileTest.h // FileTest.h
// //
// $Id: //poco/svn/Foundation/testsuite/src/FileTest.h#2 $ // $Id: //poco/Main/Foundation/testsuite/src/FileTest.h#12 $
// //
// Definition of the FileTest class. // Definition of the FileTest class.
// //
@ -49,6 +49,7 @@ public:
void testFileAttributes1(); void testFileAttributes1();
void testCreateFile(); void testCreateFile();
void testFileAttributes2(); void testFileAttributes2();
void testFileAttributes3();
void testCompare(); void testCompare();
void testSwap(); void testSwap();
void testSize(); void testSize();

View File

@ -1,7 +1,7 @@
// //
// NotificationQueueTest.cpp // NotificationQueueTest.cpp
// //
// $Id: //poco/svn/Foundation/testsuite/src/NotificationQueueTest.cpp#2 $ // $Id: //poco/Main/Foundation/testsuite/src/NotificationQueueTest.cpp#11 $
// //
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@ -38,6 +38,7 @@
#include "Poco/Thread.h" #include "Poco/Thread.h"
#include "Poco/Runnable.h" #include "Poco/Runnable.h"
#include "Poco/RunnableAdapter.h" #include "Poco/RunnableAdapter.h"
#include "Poco/Random.h"
using Poco::NotificationQueue; using Poco::NotificationQueue;
@ -46,23 +47,26 @@ using Poco::Thread;
using Poco::RunnableAdapter; using Poco::RunnableAdapter;
class QTestNotification: public Notification namespace
{ {
public: class QTestNotification: public Notification
QTestNotification(const std::string& data): _data(data)
{ {
} public:
~QTestNotification() QTestNotification(const std::string& data): _data(data)
{ {
} }
const std::string& data() const ~QTestNotification()
{ {
return _data; }
} const std::string& data() const
{
return _data;
}
private: private:
std::string _data; std::string _data;
}; };
}
NotificationQueueTest::NotificationQueueTest(const std::string& name): CppUnit::TestCase(name) NotificationQueueTest::NotificationQueueTest(const std::string& name): CppUnit::TestCase(name)
@ -171,6 +175,8 @@ void NotificationQueueTest::testWaitDequeue()
void NotificationQueueTest::testThreads() void NotificationQueueTest::testThreads()
{ {
const int NOTIFICATION_COUNT = 5000;
Thread t1("thread1"); Thread t1("thread1");
Thread t2("thread2"); Thread t2("thread2");
Thread t3("thread3"); Thread t3("thread3");
@ -179,7 +185,7 @@ void NotificationQueueTest::testThreads()
t1.start(ra); t1.start(ra);
t2.start(ra); t2.start(ra);
t3.start(ra); t3.start(ra);
for (int i = 0; i < 5000; ++i) for (int i = 0; i < NOTIFICATION_COUNT; ++i)
{ {
_queue.enqueueNotification(new Notification); _queue.enqueueNotification(new Notification);
} }
@ -189,10 +195,10 @@ void NotificationQueueTest::testThreads()
t1.join(); t1.join();
t2.join(); t2.join();
t3.join(); t3.join();
assert (_handled.size() == 5000); assert (_handled.size() == NOTIFICATION_COUNT);
assert (_handled.count("thread1") > 50); assert (_handled.count("thread1") > 0);
assert (_handled.count("thread2") > 50); assert (_handled.count("thread2") > 0);
assert (_handled.count("thread3") > 10); assert (_handled.count("thread3") > 0);
} }
@ -217,6 +223,7 @@ void NotificationQueueTest::tearDown()
void NotificationQueueTest::work() void NotificationQueueTest::work()
{ {
Poco::Random rnd;
Thread::sleep(50); Thread::sleep(50);
Notification* pNf = _queue.waitDequeueNotification(); Notification* pNf = _queue.waitDequeueNotification();
while (pNf) while (pNf)
@ -225,7 +232,7 @@ void NotificationQueueTest::work()
_mutex.lock(); _mutex.lock();
_handled.insert(Thread::current()->name()); _handled.insert(Thread::current()->name());
_mutex.unlock(); _mutex.unlock();
Thread::yield(); Thread::sleep(rnd.next(5));
pNf = _queue.waitDequeueNotification(); pNf = _queue.waitDequeueNotification();
} }
} }

View File

@ -1,7 +1,7 @@
// //
// NotificationsTestSuite.cpp // NotificationsTestSuite.cpp
// //
// $Id: //poco/svn/Foundation/testsuite/src/NotificationsTestSuite.cpp#2 $ // $Id: //poco/Main/Foundation/testsuite/src/NotificationsTestSuite.cpp#9 $
// //
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors. // and Contributors.
@ -33,6 +33,8 @@
#include "NotificationsTestSuite.h" #include "NotificationsTestSuite.h"
#include "NotificationCenterTest.h" #include "NotificationCenterTest.h"
#include "NotificationQueueTest.h" #include "NotificationQueueTest.h"
#include "PriorityNotificationQueueTest.h"
#include "TimedNotificationQueueTest.h"
CppUnit::Test* NotificationsTestSuite::suite() CppUnit::Test* NotificationsTestSuite::suite()
@ -41,6 +43,8 @@ CppUnit::Test* NotificationsTestSuite::suite()
pSuite->addTest(NotificationCenterTest::suite()); pSuite->addTest(NotificationCenterTest::suite());
pSuite->addTest(NotificationQueueTest::suite()); pSuite->addTest(NotificationQueueTest::suite());
pSuite->addTest(PriorityNotificationQueueTest::suite());
pSuite->addTest(TimedNotificationQueueTest::suite());
return pSuite; return pSuite;
} }

View File

@ -0,0 +1,234 @@
//
// PriorityNotificationQueueTest.cpp
//
// $Id: //poco/Main/Foundation/testsuite/src/PriorityNotificationQueueTest.cpp#1 $
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "PriorityNotificationQueueTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/PriorityNotificationQueue.h"
#include "Poco/Notification.h"
#include "Poco/Thread.h"
#include "Poco/Runnable.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/Random.h"
using Poco::PriorityNotificationQueue;
using Poco::Notification;
using Poco::Thread;
using Poco::RunnableAdapter;
namespace
{
class QTestNotification: public Notification
{
public:
QTestNotification(const std::string& data): _data(data)
{
}
~QTestNotification()
{
}
const std::string& data() const
{
return _data;
}
private:
std::string _data;
};
}
PriorityNotificationQueueTest::PriorityNotificationQueueTest(const std::string& name): CppUnit::TestCase(name)
{
}
PriorityNotificationQueueTest::~PriorityNotificationQueueTest()
{
}
void PriorityNotificationQueueTest::testQueueDequeue()
{
PriorityNotificationQueue queue;
assert (queue.empty());
assert (queue.size() == 0);
Notification* pNf = queue.dequeueNotification();
assertNullPtr(pNf);
queue.enqueueNotification(new Notification, 1);
assert (!queue.empty());
assert (queue.size() == 1);
pNf = queue.dequeueNotification();
assertNotNullPtr(pNf);
assert (queue.empty());
assert (queue.size() == 0);
pNf->release();
queue.enqueueNotification(new QTestNotification("first"), 1);
queue.enqueueNotification(new QTestNotification("fourth"), 4);
queue.enqueueNotification(new QTestNotification("third"), 3);
queue.enqueueNotification(new QTestNotification("second"), 2);
assert (!queue.empty());
assert (queue.size() == 4);
QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "first");
pTNf->release();
assert (!queue.empty());
assert (queue.size() == 3);
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "second");
pTNf->release();
assert (!queue.empty());
assert (queue.size() == 2);
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "third");
pTNf->release();
assert (!queue.empty());
assert (queue.size() == 1);
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "fourth");
pTNf->release();
assert (queue.empty());
assert (queue.size() == 0);
pNf = queue.dequeueNotification();
assertNullPtr(pNf);
}
void PriorityNotificationQueueTest::testWaitDequeue()
{
PriorityNotificationQueue queue;
queue.enqueueNotification(new QTestNotification("third"), 3);
queue.enqueueNotification(new QTestNotification("fourth"), 4);
assert (!queue.empty());
assert (queue.size() == 2);
QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "third");
pTNf->release();
assert (!queue.empty());
assert (queue.size() == 1);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "fourth");
pTNf->release();
assert (queue.empty());
assert (queue.size() == 0);
Notification* pNf = queue.waitDequeueNotification(10);
assertNullPtr(pNf);
}
void PriorityNotificationQueueTest::testThreads()
{
const int NOTIFICATION_COUNT = 5000;
Thread t1("thread1");
Thread t2("thread2");
Thread t3("thread3");
RunnableAdapter<PriorityNotificationQueueTest> ra(*this, &PriorityNotificationQueueTest::work);
t1.start(ra);
t2.start(ra);
t3.start(ra);
for (int i = 0; i < NOTIFICATION_COUNT; ++i)
{
_queue.enqueueNotification(new Notification, 1);
}
while (!_queue.empty()) Thread::sleep(50);
Thread::sleep(20);
_queue.wakeUpAll();
t1.join();
t2.join();
t3.join();
assert (_handled.size() == NOTIFICATION_COUNT);
assert (_handled.count("thread1") > 0);
assert (_handled.count("thread2") > 0);
assert (_handled.count("thread3") > 0);
}
void PriorityNotificationQueueTest::testDefaultQueue()
{
PriorityNotificationQueue& queue = PriorityNotificationQueue::defaultQueue();
assert (queue.empty());
assert (queue.size() == 0);
}
void PriorityNotificationQueueTest::setUp()
{
_handled.clear();
}
void PriorityNotificationQueueTest::tearDown()
{
}
void PriorityNotificationQueueTest::work()
{
Poco::Random rnd;
Thread::sleep(50);
Notification* pNf = _queue.waitDequeueNotification();
while (pNf)
{
pNf->release();
_mutex.lock();
_handled.insert(Thread::current()->name());
_mutex.unlock();
Thread::sleep(rnd.next(5));
pNf = _queue.waitDequeueNotification();
}
}
CppUnit::Test* PriorityNotificationQueueTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PriorityNotificationQueueTest");
CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testQueueDequeue);
CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testWaitDequeue);
CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testThreads);
CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testDefaultQueue);
return pSuite;
}

View File

@ -0,0 +1,72 @@
//
// PriorityNotificationQueueTest.h
//
// $Id: //poco/Main/Foundation/testsuite/src/PriorityNotificationQueueTest.h#1 $
//
// Definition of the PriorityNotificationQueueTest class.
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef PriorityNotificationQueueTest_INCLUDED
#define PriorityNotificationQueueTest_INCLUDED
#include "Poco/Foundation.h"
#include "CppUnit/TestCase.h"
#include "Poco/PriorityNotificationQueue.h"
#include "Poco/Mutex.h"
#include <set>
class PriorityNotificationQueueTest: public CppUnit::TestCase
{
public:
PriorityNotificationQueueTest(const std::string& name);
~PriorityNotificationQueueTest();
void testQueueDequeue();
void testWaitDequeue();
void testThreads();
void testDefaultQueue();
void setUp();
void tearDown();
static CppUnit::Test* suite();
protected:
void work();
private:
Poco::PriorityNotificationQueue _queue;
std::multiset<std::string> _handled;
Poco::FastMutex _mutex;
};
#endif // PriorityNotificationQueueTest_INCLUDED

View File

@ -0,0 +1,291 @@
//
// TimedNotificationQueueTest.cpp
//
// $Id: //poco/Main/Foundation/testsuite/src/TimedNotificationQueueTest.cpp#1 $
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "TimedNotificationQueueTest.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/TestSuite.h"
#include "Poco/TimedNotificationQueue.h"
#include "Poco/Notification.h"
#include "Poco/Timestamp.h"
using Poco::TimedNotificationQueue;
using Poco::Notification;
using Poco::Timestamp;
namespace
{
class QTestNotification: public Notification
{
public:
QTestNotification(const std::string& data): _data(data)
{
}
~QTestNotification()
{
}
const std::string& data() const
{
return _data;
}
private:
std::string _data;
};
}
TimedNotificationQueueTest::TimedNotificationQueueTest(const std::string& name): CppUnit::TestCase(name)
{
}
TimedNotificationQueueTest::~TimedNotificationQueueTest()
{
}
void TimedNotificationQueueTest::testDequeue()
{
TimedNotificationQueue queue;
assert (queue.empty());
assert (queue.size() == 0);
Notification* pNf = queue.dequeueNotification();
assertNullPtr(pNf);
queue.enqueueNotification(new Notification, Timestamp());
assert (!queue.empty());
assert (queue.size() == 1);
pNf = queue.dequeueNotification();
assertNotNullPtr(pNf);
assert (queue.empty());
assert (queue.size() == 0);
pNf->release();
Poco::Timestamp ts1;
ts1 += 100000;
Poco::Timestamp ts2;
ts2 += 200000;
Poco::Timestamp ts3;
ts3 += 300000;
Poco::Timestamp ts4;
ts4 += 400000;
queue.enqueueNotification(new QTestNotification("first"), ts1);
queue.enqueueNotification(new QTestNotification("fourth"), ts4);
queue.enqueueNotification(new QTestNotification("third"), ts3);
queue.enqueueNotification(new QTestNotification("second"), ts2);
assert (!queue.empty());
assert (queue.size() == 4);
QTestNotification* pTNf = 0;
while (!pTNf)
{
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
}
assertNotNullPtr(pTNf);
assert (pTNf->data() == "first");
pTNf->release();
assert (ts1.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 3);
pTNf = 0;
while (!pTNf)
{
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
}
assertNotNullPtr(pTNf);
assert (pTNf->data() == "second");
pTNf->release();
assert (ts2.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 2);
pTNf = 0;
while (!pTNf)
{
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
}
assertNotNullPtr(pTNf);
assert (pTNf->data() == "third");
pTNf->release();
assert (ts3.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 1);
pTNf = 0;
while (!pTNf)
{
pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
}
assertNotNullPtr(pTNf);
assert (pTNf->data() == "fourth");
pTNf->release();
assert (ts4.elapsed() >= 0);
assert (queue.empty());
assert (queue.size() == 0);
pNf = queue.dequeueNotification();
assertNullPtr(pNf);
}
void TimedNotificationQueueTest::testWaitDequeue()
{
TimedNotificationQueue queue;
Poco::Timestamp ts1;
ts1 += 100000;
Poco::Timestamp ts2;
ts2 += 200000;
Poco::Timestamp ts3;
ts3 += 300000;
Poco::Timestamp ts4;
ts4 += 400000;
queue.enqueueNotification(new QTestNotification("first"), ts1);
queue.enqueueNotification(new QTestNotification("fourth"), ts4);
queue.enqueueNotification(new QTestNotification("third"), ts3);
queue.enqueueNotification(new QTestNotification("second"), ts2);
assert (!queue.empty());
assert (queue.size() == 4);
QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "first");
pTNf->release();
assert (ts1.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 3);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "second");
pTNf->release();
assert (ts2.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 2);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "third");
pTNf->release();
assert (ts3.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 1);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification());
assertNotNullPtr(pTNf);
assert (pTNf->data() == "fourth");
pTNf->release();
assert (ts4.elapsed() >= 0);
assert (queue.empty());
assert (queue.size() == 0);
}
void TimedNotificationQueueTest::testWaitDequeueTimeout()
{
TimedNotificationQueue queue;
Poco::Timestamp ts1;
ts1 += 200000;
Poco::Timestamp ts2;
ts2 += 400000;
Poco::Timestamp ts3;
ts3 += 600000;
Poco::Timestamp ts4;
ts4 += 800000;
queue.enqueueNotification(new QTestNotification("first"), ts1);
queue.enqueueNotification(new QTestNotification("fourth"), ts4);
queue.enqueueNotification(new QTestNotification("third"), ts3);
queue.enqueueNotification(new QTestNotification("second"), ts2);
assert (!queue.empty());
assert (queue.size() == 4);
QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
assertNullPtr(pTNf);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(20));
assertNullPtr(pTNf);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(200));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "first");
pTNf->release();
assert (ts1.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 3);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(220));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "second");
pTNf->release();
assert (ts2.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 2);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(220));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "third");
pTNf->release();
assert (ts3.elapsed() >= 0);
assert (!queue.empty());
assert (queue.size() == 1);
pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(220));
assertNotNullPtr(pTNf);
assert (pTNf->data() == "fourth");
pTNf->release();
assert (ts1.elapsed() >= 0);
assert (queue.empty());
assert (queue.size() == 0);
}
void TimedNotificationQueueTest::setUp()
{
}
void TimedNotificationQueueTest::tearDown()
{
}
CppUnit::Test* TimedNotificationQueueTest::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimedNotificationQueueTest");
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testDequeue);
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeue);
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeueTimeout);
return pSuite;
}

View File

@ -0,0 +1,68 @@
//
// TimedNotificationQueueTest.h
//
// $Id: //poco/Main/Foundation/testsuite/src/TimedNotificationQueueTest.h#1 $
//
// Definition of the TimedNotificationQueueTest class.
//
// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#ifndef TimedNotificationQueueTest_INCLUDED
#define TimedNotificationQueueTest_INCLUDED
#include "Poco/Foundation.h"
#include "CppUnit/TestCase.h"
#include "Poco/TimedNotificationQueue.h"
#include "Poco/Mutex.h"
#include <set>
class TimedNotificationQueueTest: public CppUnit::TestCase
{
public:
TimedNotificationQueueTest(const std::string& name);
~TimedNotificationQueueTest();
void testDequeue();
void testWaitDequeue();
void testWaitDequeueTimeout();
void setUp();
void tearDown();
static CppUnit::Test* suite();
protected:
void work();
private:
};
#endif // TimedNotificationQueueTest_INCLUDED