VR-Link API Documentation for DIS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Threading Example

This is a simple example to test and show VR-Link's threading classes.

This example is composed of several classes, and several functions. The central function is called runTest().


/******************************************************************************
** Copyright (c) 1992-2010 VT MAK
** All rights reserved.
******************************************************************************/
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <iostream>
#include <set>
#include <stack>
#include <vlutil/vlMutex.h>
DtMutex iomutex;
// Thread safe print for functions.
void print_ts(const char* msg)
{
DtScopedLock lock(iomutex);
std::cout << msg << std::endl;
}
class Restaurant;
class Customer;
class Order;
class Food;
typedef DtThreadSafe<std::set<Customer*> > CustomerSet;
typedef DtThreadSafe<std::stack<Order> > OrderStack;
typedef DtThreadSafe<std::stack<Food> > FoodStack;
// Utility resource classes
class Order
{
public:
int timeToCook;
Customer* theCustomer;
};
class Food
{
public:
int timeToEat;
};
// Restaurant functions as a consumer and producer of food. It takes in
// customers and as it receives orders it make the food and serves it. Upon
// the last customer leaving, the restaurant closes.
class Restaurant : public DtRunnable
{
public:
Restaurant();
// Executes the run
virtual void run();
// Public thread safe interface
// A customer orders food.
void orderFood(Order order);
// A customer enters.
void enter(Customer* customer);
// A customer leavs.
void leave(Customer* customer);
protected:
// Internal operations
// Check to see if there are any customers.
// \retval true NO customers are in.
// \retval false Customers are in.
bool noCustomers();
// Takes an order.
Order takeOrder();
// Makes food for an order.
Food makeFood(Order order);
// Waits for a little bit.
void takeBreak();
// Close the restaurant.
void close();
protected:
CustomerSet myCustomers;
OrderStack myOrders;
};
class Customer : public DtRunnable
{
public:
// Create a customer, who goes to a restaurant.
Customer(const char* name,int time,Restaurant* res);
// Executes the run
virtual void run();
// Public thread safe interface
// Food is served to the customer.
void serveFood(Food food);
// Get name
const char* name() const;
protected:
// Internal operations
// Order food.
void orderFood();
// Waits until the customer received food.
void waitForFood();
// Customer eats food.
void eatFood();
// Customer leaves restaurant.
void leave();
protected:
const char* myName;
int myTime;
FoodStack myFoodStack;
Restaurant* myRestaurant;
};
Customer::Customer(const char* name,int time,Restaurant* res) :
myName(name),
myTime(time),
myFoodStack(std::stack<Food>()),
myRestaurant(res)
{
res->enter(this);
}
{
orderFood();
waitForFood();
eatFood();
leave();
};
const char* Customer::name() const
{
return myName;
}
void Customer::orderFood()
{
char buffer[256];
sprintf(buffer,"%s: ordering food.",myName);
print_ts(buffer);
Order order;
order.timeToCook = myTime;
order.theCustomer = this;
myRestaurant->orderFood(order);
}
void Customer::waitForFood()
{
while(myFoodStack->size() == 0) DtSleep(.5);
}
void Customer::eatFood()
{
Food food = myFoodStack->top();
myFoodStack->pop();
for(int i = 0;i < food.timeToEat;++i)
{
char buffer[256];
sprintf(buffer,"%s: Eating for %d",myName,i);
print_ts(buffer);
DtSleep(0.5);
}
}
void Customer::serveFood(Food food)
{
myFoodStack->push(food);
}
void Customer::leave()
{
char buffer[256];
sprintf(buffer,"%s: leaving restaurant",myName);
print_ts(buffer);
myRestaurant->leave(this);
}
Restaurant::Restaurant() :
myOrders(std::stack<Order>()),
myCustomers(std::set<Customer*>())
{
}
{
//Run until told to stop or no more customers
while(true)
{
if(noCustomers())
{
close();
return;
}
//Take an order, Make the food
Order order = takeOrder();
if(order.theCustomer != 0)
{
Food meal = makeFood(order);
print_ts("Restaurant: Serving food");
order.theCustomer->serveFood(meal);
}
else
{
takeBreak();
}
}
close();
}
bool Restaurant::noCustomers()
{
return myCustomers->size() == 0;
}
void Restaurant::orderFood(Order order)
{
myOrders->push(order);
}
Order Restaurant::takeOrder()
{
Order order;
order.theCustomer = 0;
{//Scope for sequence lock
DtScopedSequenceLock lock = myOrders.sequenceLock();
if(myOrders->size() > 0)
{
order = myOrders->top();
myOrders->pop();
print_ts("Restaurant: Took Order");
}
}
return order;
}
Food Restaurant::makeFood(Order order)
{
char buffer[256];
int totalTime = order.timeToCook;
while(totalTime > 0)
{
sprintf(buffer,"Restaurant: Making food: Finished in %d s",totalTime);
print_ts(buffer);
--totalTime;
DtSleep(1);
}
Food food;
food.timeToEat = order.timeToCook * 2;
return food;
}
void Restaurant::leave(Customer* customer)
{
myCustomers->erase(customer);
}
void Restaurant::enter(Customer* customer)
{
char buffer[256];
sprintf(buffer,"Restaurant: Seeting %s",customer->name());
print_ts(buffer);
myCustomers->insert(customer);
}
void Restaurant::takeBreak()
{
print_ts("Restaurant: Taking 5");
DtSleep(5);
}
void Restaurant::close()
{
print_ts("Restaurant: Closing");
}
void RunTest()
{
const char* customerNames[] =
{
"Colin",
"Jim",
"Len",
"Howard",
"Mike",
"Karen",
"Jeff",
"Jeff",
"Ben",
"Rob",
"Marshal",
"Doug",
"Aline",
"Nate",
"Fred",
"Jorge"
};
int customerCount = 16;
time_t t = time(NULL);
srand(t);
Restaurant* aRestaurant = new Restaurant();
DtThreadedObject thread0(DtRunnableSP( (DtRunnable*)aRestaurant));
Customer* customer1 = new Customer(customerNames[rand() % customerCount],2,aRestaurant);
DtThreadedObject thread1(DtRunnableSP( (DtRunnable*)customer1));
Customer* customer2 = new Customer(customerNames[rand() % customerCount],3,aRestaurant);
DtThreadedObject thread2(DtRunnableSP((DtRunnable*)customer2));
Customer* customer3 = new Customer(customerNames[rand() % customerCount],4,aRestaurant);
DtThreadedObject thread3(DtRunnableSP((DtRunnable*)customer3));
Customer* customer4 = new Customer(customerNames[rand() % customerCount],5,aRestaurant);
DtThreadedObject thread4(DtRunnableSP((DtRunnable*)customer4));
Customer* customer5 = new Customer(customerNames[rand() % customerCount],6,aRestaurant);
DtThreadedObject thread5(DtRunnableSP((DtRunnable*)customer5));
// Start all threads executing.
thread0.start();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
// Wait for all customers
thread1.join();
thread2.join();
thread3.join();
thread4.join();
thread5.join();
// Wait for restaurant.
thread0.join();
}
int main(int argc, char* argv[])
{
RunTest();
}


Document ID: Generated on Tue Mar 1 02:56:17 EST 2016 from SVN revision 162687
Copyright © 2005-2014 VT MÄK. All Rights Reserved (www.mak.com)