How to: Manage a Scheduler Instance

Scheduler instances let you associate specific scheduling policies with various kinds of workloads. This topic contains two basic examples that show how to create and manage a scheduler instance.

The examples create schedulers that use the default scheduler policies. For an example that creates a scheduler that uses a custom policy, see How to: Specify Specific Scheduler Policies.

To manage a scheduler instance in your application

  1. Create a concurrency::SchedulerPolicy object that contains the policy values for the scheduler to use.

  2. Call the concurrency::CurrentScheduler::Create method or the concurrency::Scheduler::Create method to create a scheduler instance.

    If you use the Scheduler::Create method, call the concurrency::Scheduler::Attach method when you need to associate the scheduler with the current context.

  3. Call the CreateEvent function to create a handle to a non-signaled, auto-reset event object.

  4. Pass the handle to the event object that you just created to the concurrency::CurrentScheduler::RegisterShutdownEvent method or the concurrency::Scheduler::RegisterShutdownEvent method. This registers the event to be set when the scheduler is destroyed.

  5. Perform the tasks that you want the current scheduler to schedule.

  6. Call the concurrency::CurrentScheduler::Detach method to detach the current scheduler and restore the previous scheduler as the current one.

    If you use the Scheduler::Create method, call the concurrency::Scheduler::Release method to decrement the reference count of the Scheduler object.

  7. Pass the handle to the event to the WaitForSingleObject function to wait for the scheduler to shut down.

  8. Call the CloseHandle function to close the handle to the event object.

Example

The following code shows two ways to manage a scheduler instance. Each example first uses the default scheduler to perform a task that prints out the unique identifier of the current scheduler. Each example then uses a scheduler instance to perform the same task again. Finally, each example restores the default scheduler as the current one and performs the task one more time.

The first example uses the concurrency::CurrentScheduler class to create a scheduler instance and associate it with the current context. The second example uses the concurrency::Scheduler class to perform the same task. Typically, the CurrentScheduler class is used to work with the current scheduler. The second example, which uses the Scheduler class, is useful when you want to control when the scheduler is associated with the current context or when you want to associate specific schedulers with specific tasks.

// scheduler-instance.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Prints the identifier of the current scheduler to the console.
void perform_task()
{
   // A task group.
   task_group tasks;

   // Run a task in the group. The current scheduler schedules the task.
   tasks.run_and_wait([] { 
      wcout << L"Current scheduler id: " << CurrentScheduler::Id() << endl;
   });
}

// Uses the CurrentScheduler class to manage a scheduler instance.
void current_scheduler()
{
   // Run the task.
   // This prints the identifier of the default scheduler.
   perform_task();

   // For demonstration, create a scheduler object that uses 
   // the default policy values.
   wcout << L"Creating and attaching scheduler..." << endl;
   CurrentScheduler::Create(SchedulerPolicy());

   // Register to be notified when the scheduler shuts down.
   HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   CurrentScheduler::RegisterShutdownEvent(hShutdownEvent);

   // Run the task again.
   // This prints the identifier of the new scheduler.
   perform_task();

   // Detach the current scheduler. This restores the previous scheduler
   // as the current one.
   wcout << L"Detaching scheduler..." << endl;
   CurrentScheduler::Detach();

   // Wait for the scheduler to shut down and destroy itself.
   WaitForSingleObject(hShutdownEvent, INFINITE);

   // Close the event handle.
   CloseHandle(hShutdownEvent);

   // Run the sample task again.
   // This prints the identifier of the default scheduler.
   perform_task();
}

// Uses the Scheduler class to manage a scheduler instance.
void explicit_scheduler()
{
   // Run the task.
   // This prints the identifier of the default scheduler.
   perform_task();

   // For demonstration, create a scheduler object that uses 
   // the default policy values.
   wcout << L"Creating scheduler..." << endl;
   Scheduler* scheduler = Scheduler::Create(SchedulerPolicy());

   // Register to be notified when the scheduler shuts down.
   HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   scheduler->RegisterShutdownEvent(hShutdownEvent);

   // Associate the scheduler with the current thread.
   wcout << L"Attaching scheduler..." << endl;
   scheduler->Attach();

   // Run the sample task again.
   // This prints the identifier of the new scheduler.
   perform_task();

   // Detach the current scheduler. This restores the previous scheduler
   // as the current one.
   wcout << L"Detaching scheduler..." << endl;
   CurrentScheduler::Detach();

   // Release the final reference to the scheduler. This causes the scheduler
   // to shut down after all tasks finish.
   scheduler->Release();

   // Wait for the scheduler to shut down and destroy itself.
   WaitForSingleObject(hShutdownEvent, INFINITE);

   // Close the event handle.
   CloseHandle(hShutdownEvent);

   // Run the sample task again.
   // This prints the identifier of the default scheduler.
   perform_task();
}

int wmain()
{
   // Use the CurrentScheduler class to manage a scheduler instance.
   wcout << L"Using CurrentScheduler class..." << endl << endl;
   current_scheduler();

   wcout << endl << endl;

   // Use the Scheduler class to manage a scheduler instance.
   wcout << L"Using Scheduler class..." << endl << endl;
   explicit_scheduler();
}

This example produces the following output.

Using CurrentScheduler class...

Current scheduler id: 0
Creating and attaching scheduler...
Current scheduler id: 1
Detaching scheduler...
Current scheduler id: 0

Using Scheduler class...

Current scheduler id: 0
Creating scheduler...
Attaching scheduler...
Current scheduler id: 2
Detaching scheduler...
Current scheduler id: 0

Compiling the Code

Copy the example code and paste it in a Visual Studio project, or paste it in a file that is named scheduler-instance.cpp and then run the following command in a Visual Studio Command Prompt window.

cl.exe /EHsc scheduler-instance.cpp

See also

Scheduler Instances
How to: Specify Specific Scheduler Policies