source: trunk/CrypPlugins/Libs/OpenCLNet/Event.cs @ 2040

Last change on this file since 2040 was 2040, checked in by Sven Rech, 11 years ago
  • added OpenCL.Net project
  • added OpenCL settings in KeySearcher
  • changed rereservation status message behavior
File size: 10.5 KB
Line 
1/*
2 * Copyright (c) 2009 Olav Kalgraf(olav.kalgraf@gmail.com)
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26using System;
27using System.Collections.Generic;
28using System.Linq;
29using System.Text;
30using System.Threading;
31
32namespace OpenCLNet
33{
34    public class Event : IDisposable, InteropTools.IPropertyContainer
35    {
36        #region Properties
37       
38        public IntPtr EventID { get; protected set; }
39        public Context Context { get; protected set; }
40        public CommandQueue CommandQueue { get; protected set; }
41        public ExecutionStatus ExecutionStatus { get { return (ExecutionStatus)InteropTools.ReadUInt(this, (uint)EventInfo.COMMAND_EXECUTION_STATUS); } }
42        public CommandType CommandType { get { return (CommandType)InteropTools.ReadUInt(this, (uint)EventInfo.COMMAND_TYPE); } }
43
44        #endregion
45
46        internal class CallbackData
47        {
48            public Event EventObject;
49            public EventNotify UserMethod;
50            public object UserData;
51
52            internal CallbackData(Event _event, EventNotify userMethod, object userData)
53            {
54                EventObject = _event;
55                UserMethod = userMethod;
56                UserData = userData;
57            }
58        }
59
60        private static int CallbackId;
61        private static Mutex CallbackMutex = new Mutex();
62        private static Dictionary<int, CallbackData> CallbackDispatch = new Dictionary<int, CallbackData>();
63        private static EventNotifyInternal CallbackDelegate = new EventNotifyInternal(EventCallback);
64        private static int AddCallback(Event _event, EventNotify userMethod, object userData)
65        {
66            int callbackId;
67            CallbackData callbackData = new CallbackData(_event,userMethod,userData);
68            bool gotMutex = false;
69
70            try
71            {
72                gotMutex = CallbackMutex.WaitOne();
73                do
74                {
75                    callbackId = CallbackId++;
76                } while (CallbackDispatch.ContainsKey(callbackId));
77                CallbackDispatch.Add(callbackId, callbackData);
78            }
79            finally
80            {
81                if (gotMutex)
82                    CallbackMutex.ReleaseMutex();
83            }
84            return callbackId;
85        }
86
87        private static CallbackData GetCallback(int callbackId)
88        {
89            CallbackData callbackData = null;
90            bool gotMutex = false;
91            try
92            {
93                gotMutex = CallbackMutex.WaitOne();
94                callbackData = CallbackDispatch[callbackId];
95            }
96            finally
97            {
98                if( gotMutex )
99                    CallbackMutex.ReleaseMutex();
100            }
101            return callbackData;
102        }
103
104        private static void RemoveCallback(int callbackId)
105        {
106            bool gotMutex = false;
107            try
108            {
109                gotMutex = CallbackMutex.WaitOne();
110                CallbackDispatch.Remove(callbackId);
111            }
112            finally
113            {
114                if (gotMutex)
115                    CallbackMutex.ReleaseMutex();
116            }
117        }
118
119        // Track whether Dispose has been called.
120        private bool disposed = false;
121
122        #region Construction / Destruction
123
124        internal Event( Context context, CommandQueue cq, IntPtr eventID )
125        {
126            Context = context;
127            CommandQueue = cq;
128            EventID = eventID;
129        }
130
131        // Use C# destructor syntax for finalization code.
132        // This destructor will run only if the Dispose method
133        // does not get called.
134        // It gives your base class the opportunity to finalize.
135        // Do not provide destructors in types derived from this class.
136        ~Event()
137        {
138            // Do not re-create Dispose clean-up code here.
139            // Calling Dispose(false) is optimal in terms of
140            // readability and maintainability.
141            Dispose( false );
142        }
143
144        #endregion
145
146        #region IDisposable Members
147
148        // Implement IDisposable.
149        // Do not make this method virtual.
150        // A derived class should not be able to override this method.
151        public void Dispose()
152        {
153            Dispose( true );
154            // This object will be cleaned up by the Dispose method.
155            // Therefore, you should call GC.SupressFinalize to
156            // take this object off the finalization queue
157            // and prevent finalization code for this object
158            // from executing a second time.
159            GC.SuppressFinalize( this );
160        }
161
162        // Dispose(bool disposing) executes in two distinct scenarios.
163        // If disposing equals true, the method has been called directly
164        // or indirectly by a user's code. Managed and unmanaged resources
165        // can be disposed.
166        // If disposing equals false, the method has been called by the
167        // runtime from inside the finalizer and you should not reference
168        // other objects. Only unmanaged resources can be disposed.
169        private void Dispose( bool disposing )
170        {
171            // Check to see if Dispose has already been called.
172            if( !this.disposed )
173            {
174                // If disposing equals true, dispose all managed
175                // and unmanaged resources.
176                if( disposing )
177                {
178                    // Dispose managed resources.
179                }
180
181                // Call the appropriate methods to clean up
182                // unmanaged resources here.
183                // If disposing is false,
184                // only the following code is executed.
185                OpenCL.ReleaseEvent( EventID );
186                EventID = IntPtr.Zero;
187
188                // Note disposing has been done.
189                disposed = true;
190            }
191        }
192
193        #endregion
194
195        #region IPropertyContainer Members
196
197        unsafe public IntPtr GetPropertySize( uint key )
198        {
199            IntPtr size;
200            ErrorCode result;
201
202            result = (ErrorCode)OpenCL.GetEventInfo( EventID, key, IntPtr.Zero, null, out size );
203            if( result!=ErrorCode.SUCCESS )
204                throw new OpenCLException( "GetEventInfo failed; "+result, result);
205            return size;
206        }
207
208        unsafe public void ReadProperty( uint key, IntPtr keyLength, void* pBuffer )
209        {
210            IntPtr size;
211            ErrorCode result;
212
213            result = (ErrorCode)OpenCL.GetEventInfo( EventID, key, keyLength, pBuffer, out size );
214            if( result!=ErrorCode.SUCCESS )
215                throw new OpenCLException( "GetEventInfo failed; "+result, result);
216        }
217
218        #endregion
219
220        /// <summary>
221        /// Block the current thread until this event is completed
222        /// </summary>
223        public void Wait()
224        {
225            Context.WaitForEvent(this);
226        }
227
228        /// <summary>
229        /// OpenCL 1.1
230        /// </summary>
231        /// <param name="_event"></param>
232        /// <param name="execution_status"></param>
233        public void SetUserEventStatus(ExecutionStatus execution_status)
234        {
235            ErrorCode result;
236
237            result = OpenCL.SetUserEventStatus(EventID, execution_status);
238            if (result != ErrorCode.SUCCESS)
239                throw new OpenCLException("SetUserEventStatus failed with error code " + result, result);
240        }
241
242        /// <summary>
243        /// OpenCL 1.1
244        /// </summary>
245        /// <param name="command_exec_callback_type"></param>
246        /// <param name="pfn_notify"></param>
247        /// <param name="user_data"></param>
248        public void SetCallback(ExecutionStatus command_exec_callback_type, EventNotify pfn_notify, object user_data)
249        {
250            ErrorCode result;
251            int callbackId = AddCallback(this,pfn_notify, user_data);
252
253            result = OpenCL.SetEventCallback(EventID, (int)command_exec_callback_type, CallbackDelegate, (IntPtr)callbackId);
254            if (result != ErrorCode.SUCCESS)
255                throw new OpenCLException("SetEventCallback failed with error code " + result, result);
256        }
257
258        private static void EventCallback(IntPtr eventId, int executionStatus, IntPtr userData)
259        {
260            int callbackId = userData.ToInt32();
261            CallbackData callbackData = GetCallback(callbackId);
262            callbackData.UserMethod(callbackData.EventObject, (ExecutionStatus)executionStatus, callbackData.UserData);
263            RemoveCallback(callbackId);
264        }
265
266        /// <summary>
267        /// Returns the specified profiling counter
268        /// </summary>
269        /// <param name="paramName"></param>
270        /// <param name="paramValue"></param>
271        public unsafe void GetEventProfilingInfo(ProfilingInfo paramName, out ulong paramValue)
272        {
273            IntPtr paramValueSizeRet;
274            ulong v;
275            ErrorCode errorCode;
276
277            errorCode = OpenCL.GetEventProfilingInfo(EventID, paramName, (IntPtr)sizeof(ulong), &v, out paramValueSizeRet);
278            if (errorCode != ErrorCode.SUCCESS)
279                throw new OpenCLException("GetEventProfilingInfo failed with error code "+errorCode, errorCode );
280            paramValue = v;
281        }
282
283        public static implicit operator IntPtr( Event _event )
284        {
285            return _event.EventID;
286        }
287    }
288}
Note: See TracBrowser for help on using the repository browser.