From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,8f0a6ebf5797fc5,start X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!postnews.google.com!f14g2000cwb.googlegroups.com!not-for-mail From: "Lucretia" Newsgroups: comp.lang.ada Subject: Possible solution to implementing task safety within wxAda, please comment ;-D Date: 31 Oct 2005 09:37:19 -0800 Organization: http://groups.google.com Message-ID: <1130780239.573919.126650@f14g2000cwb.googlegroups.com> NNTP-Posting-Host: 194.74.199.42 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1130780244 17877 127.0.0.1 (31 Oct 2005 17:37:24 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Mon, 31 Oct 2005 17:37:24 +0000 (UTC) User-Agent: G2/0.2 X-HTTP-UserAgent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322),gzip(gfe),gzip(gfe) X-HTTP-Via: 1.0 Symantec_Web_Security (3.0.1.74), 1.0 C2100-0050414028 (NetCache NetApp/5.5R5) Complaints-To: groups-abuse@google.com Injection-Info: f14g2000cwb.googlegroups.com; posting-host=194.74.199.42; posting-account=G-J9fgwAAADgpzBiEyy5tO4f8MX5fbpw Xref: g2news1.google.com comp.lang.ada:6076 Date: 2005-10-31T09:37:19-08:00 List-Id: I have come up with a (partial?) plan to implement task safe event handling. There is, as far as I know, only one area where task safety is required and that is in the triggering of events. There are two different places an event can be triggered: 1) Inside wxWidgets, e.g. a wxButton click event (or some other control's internal event) - this would be forwarded to a wxAda application from the C++ glue code and a proxy event created on the Ada side. 2) From inside wxAda, e.g. a new control derived from an wxAda type (wx.Core.Control.Control_Type) which triggers an event on some input action. In both cases triggering events occurs using functions in wxEvtHandler (wx.Base.Event_Handler.Event_Handler_Type in wxAda). So, if an event is triggered in the main app and there exists a number of Ada tasks which also trigger events, there could potentially be deadlock problems if they're all sending events to the same Event_Handler_Type. A solution could be to create a protected type which wraps around certain wxEvtHandler_* C function wrappers. Do we need to wrap every C function wrapper for the event handler inside this protected object? This protected type could then be instantiated in each Event_Handler_Type, thus the request to Event_Handler_Type's primitives could then call the protected type. Any access to this protected type would synchronise all requests to trigger events. wxEvtHandler::AddPendingEvent - Asynchronous wxEvtHandler::ProcessEvent - Synchronous Given a protected object in Ada, is it possible to lock on the C++ side as well? Do we need to? Here's some code - which hasn't been tested - which should illustrate the problem (and structure of the code) more clearly: // We have to derive a new class for this type to implement virtuals correctly - although this hasn't been shown. class wxAdaEvtHandler : public wxEvtHandler { DECLARE_DYNAMIC_CLASS(wxAdaEvtHandler); public: wxAdaEvtHandler() : wxEvtHandler() { } virtual ~wxAdaEvtHandler() { } void AddPendingEvent(wxEvent& event) { // Do we need to lock here? wxEvtHandler::AddPendingEvent(event); // Do we need to unlock here? } virtual bool ProcessEvent(wxEvent& event) { // Do we need to lock here? wxEvtHandler::ProcessEvent(event); // Do we need to unlock here? } }; /* We implement the C wrappers aound the C++ class here. */ extern "C" { void wxEvtHandler_AddPendingEvent(wxAdaEvtHandler *Self, wxEvent *Event) { Self->AddPendingEvent(*Event); } void wxEvtHandler_ProcessEvent(wxAdaEvtHandler *Self, wxEvent *Event) { Self->AddPendingEvent(*Event); } }; package wx.Base.Event_Handler is type Event_Handler_Type is new wx.Base.Object.Object_Type with private; procedure Add_Pending_Event(Self : in out Event_Handler_Type; Event : in wxEvent.Event_Type); function Process_Event(Self : in Event_Handler_Type; Event : in wxEvent.Event_Type) return Boolean; private protected type Protected_Handler_Type is procedure Add_Pending_Event(Self, Event : in System.Address); procedure Process_Event(Self, Event : in System.Address); end Protected_Handler_Type; type Event_Handler_Type is new wx.Base.Object.Object_Type with record P : Protected_Handler_Type; end record; end wx.Base.Event_Handler; package body wx.Base.Event_Handler is procedure Add_Pending_Event(Self : in out Event_Handler_Type; Event : in wxEvent.Event_Type) is begin Self.P.Add_Pending_Event(Get_wxObject(Self), Get_wxObject(Event)); end Add_Pending_Event; function Process_Event(Self : in Event_Handler_Type; Event : in wxEvent.Event_Type) return Boolean is begin Self.P.Process_Event(Get_wxObject(Self), Get_wxObject(Event)); end Process_Event; protected body Protected_Handler_Type is procedure Add_Pending_Event(Self, Event : in System.Address) is procedure AddPendingEvent(Self, Event : in System.Address); pragma Import(C, AddPendingEvent, "wxEvtHandler_AddPendingEvent"); begin -- This call returns immediately. AddPendingEvent(Self, Event); end Add_Pending_Event; procedure Process_Event(Self, Event : in System.Address) is function ProcessEvent(Self, Event : in System.Address) return Interfaces.C.int; pragma Import(C, ProcessEvent, "wxEvtHandler_ProcessEvent"); begin -- This call will process the event and then return. ProcessEvent(Self, Event); end Process_Event; end Protected_Handler_Type; end wx.Base.Event_Handler; The alternative would be to wrap each and every Event_Handler_Type created inside a protected object which would then be called instead of the actual instance, this I think, would be problematic. Thanks, Luke.