// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// TaskCollection.h
//
// Miscellaneous internal support structure definitions for a task collection
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
// The amount that we resize the task stack by per alloc.
//
#define TASK_STACK_GROWTH_SIZE 8
//
// The number of chores that we cap the task stack at. If after this many tasks are pushed, another is -- it cannot
// be inlined and will cause performance penalty for out-of-order WSQ utilization.
//
#define TASK_STACK_SIZE_CAP 1024
// **************************************************************************
// The phases of task collection cancellation (particularly for unstructured task collections).
// **************************************************************************
//
// The exit status mask (indicating which portion actively indicates status)
//
#define EXIT_CANCELLATION_MASK 0x3FFFFFFF
//
// Indicates that an exception has happened and while cancellation may proceed in due course, the end result should
// be a thrown exception.
//
#define EXIT_STATUS_FLAG_EXCEPTION_RAISED 0x80000000
//
// Indicates that the cancellation exception was thrown because cancellation was detected. The phases of cancellation are defined below.
//
#define EXIT_STATUS_FLAG_CANCELLATION_RAISED 0x40000000
//
// Indicates that cancel has started on the task collection.
//
#define EXIT_STATUS_START_CANCEL 0x00000001
// **************************************************************************
// Execution status meanings: Execution status is used for cancellation of the original task collection and its direct aliases
// **************************************************************************
//
// The task collection is in clear state -- it's not inlined, it's not canceled, etc...
//
#define TASKCOLLECTION_EXECUTION_STATUS_CLEAR 0
//
// The task collection is inlined.
//
#define TASKCOLLECTION_EXECUTION_STATUS_INLINE 1
//
// The task collection's cancellation for this alias was deferred because it was not inline.
//
#define TASKCOLLECTION_EXECUTION_STATUS_CANCEL_DEFERRED 3
//
// The cancellation is complete on the arbitrary thread.
//
#define TASKCOLLECTION_EXECUTION_STATUS_CANCEL_COMPLETE 4
//
// The task collection is inlined and about to wait for stolen chores yet the task stack has overflowed. This requires
// extra care during cancellation.
//
#define TASKCOLLECTION_EXECUTION_STATUS_INLINE_WAIT_WITH_OVERFLOW_STACK 5 // 4 | TASKCOLLECTION_EXECUTION_STATUS_INLINE
//
// The task collection is inlined and a cancellation is in progress some arbitrary thread.
//
#define TASKCOLLECTION_EXECUTION_STATUS_INLINE_CANCEL_IN_PROGRESS 9 // 8 | TASKCOLLECTION_EXECUTION_STATUS_INLINE
// **************************************************************************
// Task collection flags:
// **************************************************************************
//
// This is an indirect alias.
//
#define TASKCOLLECTIONFLAG_ALIAS_IS_INDIRECT 1
//
// The entity involved in aliasing which views this flag is responsible for cleaning up the alias.
//
#define TASKCOLLECTIONFLAG_ALIAS_FREE_ON_VIEW 2
// **************************************************************************
// Related flags:
// **************************************************************************
//
// The bit indicating that this pointer is a registration rather than a token
//
#define TASKCOLLECTIONFLAG_POINTER_IS_REGISTRATION 1
// **************************************************************************
// Class definitions:
// **************************************************************************
namespace Concurrency
{
namespace details
{
///
/// This class is an *INTERNAL* structure which will retain specific optimizations to keeping track
/// of tasks associated with an unstructured task collection.
///
class TaskStack
{
public:
///
/// Constructs a new task stack
///
TaskStack() : m_stackSize(0), m_stackPtr(0), m_pStack(NULL), m_fOverflow(false)
{
}
///
/// Destroys a task stack
///
~TaskStack();
///
/// Pushes an element onto the task stack. Returns a bool as to whether this could happen or not. The only
/// possible error here is out of memory.
///
///
/// The task cookie to push onto the stack
///
///
/// An indication of whether the stack cap was reached.
///
bool Push(int taskCookie);
///
/// Pops an element from the task stack.
///
///
/// The element
///
int Pop();
///
/// Returns an indication of whether or not the stack is empty.
///
bool IsEmpty() const;
///
/// Clears out everything on the stack. Does *NOT* reset the overflow flag.
///
void Clear();
///
/// Resets the overflow flag.
///
void ResetOverflow()
{
m_fOverflow = false;
}
///
/// An indication if the stack overflowed (was pushed beyond the cap).
///
bool Overflow() const
{
return m_fOverflow;
}
private:
int m_stackSize;
int m_stackPtr;
int *m_pStack;
bool m_fOverflow;
};
#define EVENT_UNSIGNALED ((void*) 0)
#define EVENT_SIGNALED ((void*) 1)
///
/// A single fire (non-resettable) event supporting a single waiter.
///
class StructuredEvent
{
public:
///
/// Constructs a new structured event.
///
StructuredEvent()
: m_ptr(EVENT_UNSIGNALED)
{
}
///
/// Waits until the event is signaled (via some other context calling Set())
///
void Wait();
///
/// Set the event as signaled, and unblock any other contexts waiting on the event.
///
void Set();
private:
void * volatile m_ptr;
};
///
/// Context record for WSQ sweeps.
///
struct SweeperContext
{
///
/// Constructs a new sweeper context.
///
SweeperContext(_TaskCollection *pTaskCollection) :
m_pTaskCollection(pTaskCollection),
m_sweptChores(0)
{
}
_TaskCollection *m_pTaskCollection;
unsigned int m_sweptChores;
};
} // namespace details
} // namespace Concurrency