* Possible solution to implementing task safety within wxAda, please comment ;-D
@ 2005-10-31 17:37 Lucretia
0 siblings, 0 replies; only message in thread
From: Lucretia @ 2005-10-31 17:37 UTC (permalink / raw)
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:
<example code>
// 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;
</example code>
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.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-10-31 17:37 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-31 17:37 Possible solution to implementing task safety within wxAda, please comment ;-D Lucretia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox