summaryrefslogtreecommitdiff
path: root/avstream/avscamera/sys/WorkItem.cpp
blob: 64f6238bcef081cb83dd33b79aeaf181654c364e (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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/**************************************************************************

    A/V Stream Camera Sample

    Copyright (c) 2014, Microsoft Corporation.

    File:

        workitem.cpp

    Abstract:

        This module contains an implementation for KWorkItem.

        A KWorkItem inherits from CRef and is reference counted.  The object 
        cannot be destroyed until all references are released.  This includes
        the reference held when the workitem is in flight.  This allows you 
        to store the workitem in an object that has a lifecycle shorter than
        the parent device object.

    History:

        created 5/30/2014

**************************************************************************/

#include "Common.h"

KWorkItem::
KWorkItem(
    _In_    PDEVICE_OBJECT          DeviceObj,
    _In_    PIO_WORKITEM_ROUTINE    Callback,
    _In_    PVOID                   Context,
    _In_    WORK_QUEUE_TYPE         QueueType
)
    : m_Callback( Callback )
    , m_Context ( Context  )
    , m_QueueType( QueueType )
/*++

Routine Description:

    Constructor.  
    
    Sets up callback handler for the workitem and performs initialization.

Arguments:

    None.

Return Value:

    None.

--*/
{
    m_WorkItem = IoAllocateWorkItem( DeviceObj );
}


KWorkItem::
~KWorkItem()
/*++

Routine Description:

    Destructor.  
    
    Blocks until all references are released, then frees the workitem.

Arguments:

    None.

Return Value:

    None.

--*/
{
    //  Make sure the work item has been run down.
    Wait();

    //  Now delete it.
    if( m_WorkItem )
    {
        IoFreeWorkItem( m_WorkItem );
    }
}

BOOLEAN
KWorkItem::
Start()
/*++

Routine Description:

    Enqueue this workitem and acquires a reference on the object.

Arguments:

    None.

Return Value:

    TRUE - a workitem was scheduled.

--*/
{
    //  Make sure construction succeeded.
    if( m_WorkItem )
    {
        //  Make sure the work item isn't already in flight and acquire the lock.
        //  This is to make sure this KWorkItem doesn't get destroyed until
        //  the callback is complete.
        if( Acquire() )
        {
            //  Schedule the work item.
            IoQueueWorkItem( m_WorkItem, &KWorkItem::Handler, m_QueueType, this );

            //  Note: Release() is called in Handler.
            return TRUE;
        }
    }
    return FALSE;
}

VOID
KWorkItem::
Handler(
    _In_        PDEVICE_OBJECT  IoObject,
    _In_opt_    PVOID           Context
)
/*++

Routine Description:

    Callback thunking function.

    Calls the callback handler registered in the constructor, if one exists.
    Releases the reference on this object.

Arguments:

    IoObject - 
        The parent device object.
    Context -
        An optional context object.

Return Value:

    void

--*/
{
    //  Get our "this" pointer (Me).
    KWorkItem *Me = (KWorkItem *) Context;

    //  Invoke the callback if one exists.
    if (Me)
    {
        if (Me->m_Callback)
        {
            Me->m_Callback(IoObject, Me->m_Context);
        }

        //  Unlock the work item; allow for destruction or re-enqueing.
        Me->Release();
    }
}