(file) Return to ChildList.h CVS log (file) (dir) Up to [OMI] / omi / miapi

  1 krisbash 1.1 /*============================================================================
  2               * Copyright (C) Microsoft Corporation, All rights reserved. 
  3               *============================================================================
  4               */
  5              #ifndef _miapi_childlist_h_
  6              #define _miapi_childlist_h_
  7              #include <MI.h>
  8              #include "SafeHandle.h"
  9              #include <pal/lock.h>
 10              #include <pal/atomic.h>
 11              
 12              typedef struct _ChildListNode
 13              {
 14                  struct _ChildListNode *left;
 15                  struct _ChildListNode *right;
 16                  GenericHandle clientHandle;     /* Client handle for object so Cancel can be called on it */
 17              }
 18              ChildListNode;
 19              
 20              typedef struct _ChildListOutstandingHandles
 21              {
 22 krisbash 1.1     GenericHandle clientHandle;     /* Client handle for object so Cancel can be called on it */
 23                  GenericHandle *debugHandlePointer;  /* Pointer of original for debugging purposes only, do not dereference it as it may be invalid */
 24              } 
 25              ChildListOutstandingHandles;
 26              
 27              typedef struct _ChildList
 28              {
 29                  ChildListNode *headNode;
 30                  volatile ptrdiff_t childCount;
 31                  volatile MI_Boolean shutdown;
 32                  CachedLock lock;
 33              
 34                  void (*shutdownCompleteCallback)(void *context);
 35                  void *shutdownCompleteCallbackContext;
 36              }
 37              ChildList;
 38              
 39              MI_INLINE MI_Result ChildList_Initialize(_Out_ ChildList *list)
 40              {
 41                  memset(list, 0, sizeof(ChildList));
 42                  if (CachedLock_Init(&list->lock, CACHEDLOCK_FLAG_SHARED) == 0)
 43 krisbash 1.1     {
 44                      return MI_RESULT_OK;
 45                  }
 46                  else
 47                  {
 48                      return MI_RESULT_SERVER_LIMITS_EXCEEDED;
 49                  }
 50              }
 51              MI_INLINE void ChildList_DeInitialize(_Inout_ ChildList *list)
 52              {
 53                  CachedLock_Destroy(&list->lock);
 54              }
 55              
 56              MI_INLINE MI_Result ChildList_AddNode(_Inout_ ChildList *list, _Inout_ ChildListNode *newNode)
 57              {
 58                  MI_Result retValue = MI_RESULT_OK;
 59              
 60                  if (!list->shutdown)
 61                  {
 62                      CachedLock_AcquireWrite(&list->lock);
 63              
 64 krisbash 1.1         if (!list->shutdown)
 65                      {
 66                          Atomic_Inc(&list->childCount);
 67              
 68                          /* previous head point left points to new node */
 69                          if (list->headNode)
 70                          {
 71                              list->headNode->left = newNode;
 72                          }
 73                          /* new node point to previous head */
 74                          newNode->left = NULL;
 75                          newNode->right = list->headNode;
 76              
 77                          /* set list head node to new node */
 78                          list->headNode = newNode;
 79                      }
 80                      else
 81                      {
 82                          retValue = MI_RESULT_SERVER_IS_SHUTTING_DOWN;
 83                      }
 84              
 85 krisbash 1.1         CachedLock_ReleaseWrite(&list->lock);
 86                  }
 87                  else
 88                  {
 89                      retValue = MI_RESULT_SERVER_IS_SHUTTING_DOWN;
 90                  }
 91              
 92                  return retValue;
 93              }
 94              
 95              MI_INLINE void ChildList_RemoveNode(_Inout_ ChildList *list, _In_ ChildListNode *removeNode)
 96              {
 97                  int makeShutdownCallbackNow = 0;
 98              
 99                  CachedLock_AcquireWrite(&list->lock);
100              
101                  if (list->headNode == removeNode)
102                  {
103                      list->headNode = removeNode->right;
104                  }
105                  if (removeNode->left)
106 krisbash 1.1     {
107                      removeNode->left->right = removeNode->right;
108                  }
109                  if (removeNode->right)
110                  {
111                      removeNode->right->left = removeNode->left;
112                  }
113              
114                  if ((Atomic_Dec(&list->childCount) == 0) &&
115                      list->shutdown &&
116                      list->shutdownCompleteCallback)
117                  {
118                      makeShutdownCallbackNow = 1;
119                  }
120              
121                  CachedLock_ReleaseWrite(&list->lock);
122              
123                  if (makeShutdownCallbackNow)
124                  {
125                      list->shutdownCompleteCallback(list->shutdownCompleteCallbackContext);
126                  }
127 krisbash 1.1 }
128              
129              /* Shutdown returns a list of generic handles that are still in the list.  These are not pointers to th handles (except the debug pointer)
130               * so if the handle gets closed these handles will not cause a crashes
131               */
132              MI_INLINE int ChildList_Shutdown(_Inout_ ChildList *list)
133              {
134                  int returnVal = 0;
135                  CachedLock_AcquireWrite(&list->lock);
136              
137                  if (list->shutdown == MI_FALSE)
138                  {
139                      list->shutdown = MI_TRUE;
140                      returnVal = 1;
141                  }
142              
143                  CachedLock_ReleaseWrite(&list->lock);
144              
145                  return returnVal;
146              }
147              
148 krisbash 1.1 _Success_(return == 1)
149              MI_INLINE int ChildList_GetCurrentList(_Inout_ ChildList *list, _Out_cap_post_count_(inboundSize, *outboundUsed) ChildListOutstandingHandles *outstandingHandles, ptrdiff_t inboundSize, _Out_ ptrdiff_t *outboundUsed)
150              {
151                  int returnVal = 0;
152                  CachedLock_AcquireWrite(&list->lock);
153              
154                  *outboundUsed = 0;
155              
156                  if (inboundSize >=  list->childCount)
157                  {
158                      ChildListNode *currentNode = list->headNode;
159                      (*outboundUsed) = 0;
160                      while (currentNode && 
161                          ((*outboundUsed) < inboundSize))    //redumbdant check to shut prefast up, it does not know list->childCount is how many items in list
162                      {
163                          outstandingHandles[*outboundUsed].clientHandle = currentNode->clientHandle;
164                          outstandingHandles[*outboundUsed].debugHandlePointer = &currentNode->clientHandle;
165                          
166                          currentNode = currentNode->right;
167                          (*outboundUsed) ++;
168                      }
169 krisbash 1.1         if ((*outboundUsed) < inboundSize)
170                      {
171                          returnVal = 1;
172                      }
173                      else
174                      {
175                          //never happen!
176                          (*outboundUsed) = 0;
177                      }
178                  }
179                  else
180                  {
181                      *outboundUsed = list->childCount;
182                  }
183              
184                  CachedLock_ReleaseWrite(&list->lock);
185              
186                  return returnVal;
187              }
188              
189              
190 krisbash 1.1 MI_INLINE void ChildList_RegisterShutdownCallback(
191                  _Inout_ ChildList *list,
192                  _In_ void (*shutdownCompleteCallback)(void *context),
193                  _In_ void *shutdownCompleteCallbackContext)
194              {
195                  int makeShutdownCallbackNow = 0;
196              
197                  CachedLock_AcquireWrite(&list->lock);
198              
199                  if ((list->shutdown == MI_TRUE) &&
200                      (list->childCount == 0))
201                  {
202                      makeShutdownCallbackNow = 1;
203                  }
204                  else
205                  {
206                      list->shutdownCompleteCallbackContext = shutdownCompleteCallbackContext;
207                      list->shutdownCompleteCallback = shutdownCompleteCallback;
208                  }
209              
210                  CachedLock_ReleaseWrite(&list->lock);
211 krisbash 1.1 
212                  if (makeShutdownCallbackNow)
213                  {
214                      shutdownCompleteCallback(shutdownCompleteCallbackContext);
215                  }
216              
217              }
218              #endif /* _miapi_childlist_h_ */

ViewCVS 0.9.2