summaryrefslogtreecommitdiff
path: root/docs/tutorials/013/block.h
blob: 26604a57e4c77ea7f3da66cac9f36c94db7a8f03 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

// $Id$

#ifndef BLOCK_H
#define BLOCK_H

#include "ace/Message_Block.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

#include "ace/Synch.h"
#include "mld.h"
#include "work.h"

/*
   In this Tutorial, we derive from ACE_Data_Block for our special data.  With
   the possiblilty that our Task object may forward the unit of work on to
   another thread pool, we have to make sure that the data object doesn't go
   out of scope unexpectedly.  An ACE_Message_Block will be deleted as soon as
   it's release() method is called but the ACE_Data_Blocks it uses are
   reference counted and only delete when the last reference release()es the
   block.  We use that trait to simply our object memory management.
 */
class Data_Block : public ACE_Data_Block
{
public:
  typedef ACE_Data_Block inherited;

  // Create a data block with a unit of work to be done
    Data_Block (Unit_Of_Work * _data);

   ~Data_Block (void);

  // Returns the work pointer
  Unit_Of_Work *data (void);

protected:
    Unit_Of_Work * data_;
    MLD;                        // Our memory leak detector

  // The ACE_Data_Block allows us to choose a locking strategy
  // for making the reference counting thread-safe.  The
  // ACE_Lock_Adaptor<> template adapts the interface of a
  // number of lock objects so thatthe ACE_Message_Block will
  // have an interface it can use.
  class Lock : public ACE_Lock_Adapter < ACE_Mutex >
  {
public:
    typedef ACE_Lock_Adapter < ACE_Mutex > inherited;

      Lock (void);
     ~Lock (void);

    // When the Data_Block is destroyed, the Message_Block is
    // holding a lock with this object.  If we were to destroy
    // the Lock with the Data_Block, we would have a
    // segfault.  Instead, the Data_Block invokes destroy() to
    // mark the object as un-needed so that when the
    // Message_Block invokes release() to drop the lock, the
    // Lock can delete itself.
    int destroy (void);
    int release (void);
protected:
    int destroy_;
      MLD;
  };
};

/*
   This simple derivative of ACE_Message_Block will construct our Data_Block
   object to contain a unit of work.
 */
class Message_Block : public ACE_Message_Block
{
public:
  typedef ACE_Message_Block inherited;

    Message_Block (void);
    Message_Block (Unit_Of_Work * _data);

   ~Message_Block (void);

protected:
    MLD;
};

#endif