File: mandel_global.adb

package info (click to toggle)
libadabindx 0.7.2-4
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 3,136 kB
  • ctags: 32
  • sloc: ada: 35,597; makefile: 556; sh: 10
file content (373 lines) | stat: -rw-r--r-- 13,000 bytes parent folder | download
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
-------------------------------------------------------------------------------
--                                                                           --
--  Ada Interface to the X Window System and Motif(tm)/Lesstif               --
--  Copyright (c) 1996-2000 Hans-Frieder Vogt                                --
--                                                                           --
--  This program is free software; you can redistribute it and/or modify     --
--  it under the terms of the GNU General Public License as published by     --
--  the Free Software Foundation; either version 2 of the License, or        --
--  (at your option) any later version.                                      --
--                                                                           --
--  This program is distributed in the hope that it will be useful,          --
--  but WITHOUT ANY WARRANTY; without even the implied warranty of           --
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     --
--  See the GNU General Public License for more details.                     --
--                                                                           --
--  You should have received a copy of the GNU General Public License        --
--  along with this program; if not, write to the                            --
--  Free Software Foundation, Inc.,                                          --
--  59 Temple Place - Suite 330,                                             --
--  Boston, MA 02111-1307, USA.                                              --
--                                                                           --
--                                                                           --
--  X Window System is copyrighted by the X Consortium                       --
--  Motif(tm)       is copyrighted by the Open Software Foundation, Inc.     --
--                                                                           --
--                                                                           --
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
--
-- HISTORY:
-- 25.1.98 adapted to adabindx 0.5
--  26 Jan 2002 H.-F. Vogt: simplified the task (no start/stop any longer)
--                          admittedly the new method is quite brutal (abort..),
--                          but with the old method a deadlock occured that I
--                          don't understand and thus couldn't resolve
--                          So let's use this method until someone explains me
--                          how to do it in a better way
--  02 Mar 2002 H.-F. Vogt: replaced System.Unsigned_Types by Interfaces.C
--                          
--
-------------------------------------------------------------------------------

with Ada.Characters.Latin_1,
     Ada.Numerics.Generic_Elementary_Functions,
     Ada.Text_Io,
     Ada.Unchecked_Deallocation,
     Interfaces.C,
     X_Lib.Cursor,
     Xm_Widgets.Primitive.Label.Toggle_Button,
     Xm_Widgets.Manager.Bulletin_Board.Message_Box,
     Xm_Widgets.Manager.Drawing_Area;
use  Interfaces.C,
     Xm_Widgets.Primitive.Label,
     Xm_Widgets.Manager.Bulletin_Board.Message_Box;
package body Mandel_Global is

   package Real_Functions is
      new Ada.Numerics.Generic_Elementary_Functions (Real);
   use Real_Functions;

   procedure Free is
      new Ada.Unchecked_Deallocation (Calculate_Mandel, Calculate_Mandel_Access);

   -- locally needed Variables
   --
   W, H  : X_Lib.Dimension;
   Scale : Real;


   procedure Set_Size (Width, Height : in X_Lib.Dimension) is
      Tmp_Scale        : Real;
   begin
      W := Width;
      H := Height;
      Scale := (R_Max-R_Min) / Real (W);
      Tmp_Scale := (I_Max-I_Min) / Real (H);
      if Scale < Tmp_Scale then
	 Scale := Tmp_Scale;
      end if;
   end Set_Size;


   protected Output is
      procedure Put (S : in String);
      procedure Put_Line (S : in String);
   end Output;
   
   protected body Output is
      procedure Put (S : in String) is
      begin
         Ada.Text_Io.Put (S);
	 Ada.Text_Io.Flush;
      end Put;

      procedure Put_Line (S : in String) is
      begin
         Ada.Text_Io.Put_Line (S);
	 Ada.Text_Io.Flush;
      end Put_Line;
   end Output;


   protected Task_Counter is
      procedure Increment;
      procedure Decrement;
      function Current_Value return Natural;
      procedure Set_Value (Value : in Natural);
   private
      Counter : Natural := 0;
   end Task_Counter;

   protected body Task_Counter is

      procedure Actualize_Global_Status (Running : Boolean) is
      begin
	 Xm_Widgets.Primitive.Label.Toggle_Button.Xm_Toggle_Button_Set_State (Calc_Toggle, Running, False);
         if Running then
	    X_Lib.Cursor.X_Define_Cursor (Display, Xt_Window (The_Draw), Working_Cursor);
	 else
	    X_Lib.Cursor.X_Undefine_Cursor (Display, Xt_Window (The_Draw));
	 end if;
	 X_Lib.X_Flush (Display);
      end Actualize_Global_Status;

      procedure Increment is
      begin
         Counter := Counter + 1;
	 Output.Put_Line ("running tasks: " & Natural'Image (Counter));
	 if Counter = 1 then  -- must just have been switched on
            Actualize_Global_Status (True);
	 end if;
      end Increment;

      procedure Decrement is
      begin
         Counter := Counter - 1;
	 Output.Put_Line ("running tasks: " & Natural'Image (Counter));
	 if Counter < 1 then  -- must just have been switched on
            Actualize_Global_Status (False);
	 end if;
      end Decrement;

      function Current_Value return Natural is
      begin
         return Counter;
      end Current_Value;

      procedure Set_Value (Value : in Natural) is
      begin
         if Counter > 0 and then Value < 1 then
	    Actualize_Global_Status (False);
	 end if;
         if Counter < 1 and then Value > 0 then
	    Actualize_Global_Status (True);
	 end if;
         Counter := Value;
      end Set_Value;

   end Task_Counter;


   function Iteration (XR, YI : in X_Lib.Position;
                       Scale  : in Real) return Natural is
      X_Re     : constant Real := R_Min + Real (XR) * Scale;
      Y_Im     : constant Real := I_Min + Real (YI) * Scale;
      Infinity : constant := 1000.0;
      Iter     : Natural  := 0;
      X, Y     : Real     := 0.0;
      Dummy    : Real;
   begin
      loop
         Dummy := X;
	 X := X*X - Y*Y   + X_Re;
	 Y := 2.0*Dummy*Y + Y_Im;
	 Iter  := Iter + 1;
	 exit when (X*X+Y*Y > Infinity)
	   or else (Iter >= Max_Iterations);
      end loop;
      return Iter;
   end Iteration;



   task body Calculate_Mandel is
      I, J             : X_Lib.Position;
   begin
      J := X_Lib.Position (Offset);
      Task_Counter.Increment;
      loop
--	 Output.Put_Line ("task " & Our_Task_ID'Image (Task_ID) & " is working");
  	 I := 0;
	 Outer_Loop:
	 loop
	    for K in 1 .. 10 loop
	       exit Outer_Loop when I >= X_Lib.Position (W);
	       X_Lib.X_Draw_Point (Display, Pixmap,
	  	 GC_Table ((Iteration (I, J, Scale) - 1) mod
	  	      Num_Colors + 1), I, J);
	       I := I + 1;
	    end loop;
	    delay Duration'Small;
	 end loop Outer_Loop;
	 if Xt_Is_Realized (The_Draw) then
	    X_Lib.X_Copy_Area (Display, Pixmap, Xt_Window (The_Draw),
	  		       GC_Copy, 0, 0, W, H, 0, 0);
	 end if;
	 J := J + X_Lib.Position (Jump);
         if J >= X_Lib.Position (H) then
            Task_Counter.Decrement;
	    exit;
         end if;
         delay Duration'Small;
      end loop;
   end Calculate_Mandel;


   procedure Start_Calculation is
   begin
      -- first ensure that the tasks don't already exist
      --
      for I in Task_List'Range loop
         if Task_List (I) /= null then
            abort Task_List (I).all;
	    Free (Task_List (I));
            Task_List (I) := null;
	 end if;
      end loop;
      Task_Counter.Set_Value (0);
      
      for I in Task_List'Range loop
	 Task_List (I) :=
	  new Calculate_Mandel (I,
				X_Lib.Dimension (I-Task_List'First),
				X_Lib.Dimension (Num_Tasks));
      end loop;
   end Start_Calculation;


   procedure Stop_Calculation is
   begin
      for I in Task_List'Range loop
         if Task_List (I) /= null then
            Output.Put_Line ("time to stop for task " & Our_Task_ID'Image (I));
	    abort Task_List (I).all;
	    Free (Task_List (I));
	    Task_List (I) := null;
            Output.Put_Line ("task " & Our_Task_ID'Image (I) & " should have stopped now");
         end if;
      end loop;
      Task_Counter.Set_Value (0);
   end Stop_Calculation;


   procedure Initialize_Threads is
   begin
      null;
   end Initialize_Threads;


   procedure Calculate_CB (W         : in Widget;
                           Closure   : in Xt_Pointer;
                           Call_Data : in Xt_Pointer) is
   begin
      if Xm_Widgets.Primitive.Label.Toggle_Button.Xm_Toggle_Button_Get_State (Calc_Toggle) then
         Start_Calculation;
      else
         Stop_Calculation;
      end if;
   end Calculate_CB;


   procedure About_CB (W         : in Widget;
                       Closure   : in Xt_Pointer;
                       Call_Data : in Xt_Pointer) is
      use Ada.Characters.Latin_1;
      Button : Widget;
      About_Text : constant String := "Mandel -- a Mandelbrot set generator" &
                                      LF &
				      "demonstrating use of multithreaded programming" & LF &
                                      "(c)1997-2002 Hans-Frieder Vogt" &
                                      LF &
                                      "(example program for Ada binding to X and Motif(tm))";
      About_String : Xm_String;
   begin
      if About_Dialog = Null_Widget then
         About_Dialog := Xm_Create_Information_Dialog (Appshell, "about_dialog");

         About_String := Xm_String_Create_L_To_R (About_Text,
                                                  Xm_String_ISO8859_1);
         Argl := Null_Arg_List;
         Append_Set (Argl, Xm_N_Message_String, About_String);
         Xt_Set_Values (About_Dialog, Argl);
         Xm_String_Free (About_String);

         Button := Xt_Name_To_Widget (About_Dialog, Cancel_Button_Name);
         Xt_Unmanage_Child (Button);
         Button := Xt_Name_To_Widget (About_Dialog, Help_Button_Name);
         Xt_Unmanage_Child (Button);
         Xt_Manage_Child (About_Dialog);
      else
         if not Xt_Is_Managed (About_Dialog) then
            Xt_Manage_Child (About_Dialog);
         end if;
      end if;
   end About_CB;


   procedure Quit_CB (W         : in Widget;
                      Closure   : in Xt_Pointer;
                      Call_Data : in Xt_Pointer) is
   begin
      Stop_Calculation;
      Xt_App_Set_Exit_Flag (App_Con);
   end Quit_CB;


   procedure Expose_CB (W         : in Widget;
                        Closure   : in Xt_Pointer;
                        Call_Data : in Xt_Pointer) is
      use Xm_Widgets.Manager.Drawing_Area, X_Lib;
      CB_Struct : Xm_Drawing_Area_Callback_Struct_Access;
      Event     : X_Event_Pointer;
   begin
      CB_Struct := To_Callback_Struct (Call_Data);
      Event     := CB_Struct.Event;
      if Event.Ev_Type /= Expose then
         return;
      end if;

      if Xt_Is_Realized (The_Draw) then
         X_Lib.X_Copy_Area (Display, Pixmap, Xt_Window (The_Draw), GC_Copy,
                            X_Lib.Position  (Event.X_Expose.X),
                            X_Lib.Position  (Event.X_Expose.Y),
                            X_Lib.Dimension (Event.X_Expose.Width),
                            X_Lib.Dimension (Event.X_Expose.Height),
                            X_Lib.Position  (Event.X_Expose.X),
                            X_Lib.Position  (Event.X_Expose.Y));
      end if;
   end Expose_CB;


   procedure Resize_CB (W         : in Widget;
                        Closure   : in Xt_Pointer;
                        Call_Data : in Xt_Pointer) is
      use Xm_Widgets.Manager.Drawing_Area, X_Lib;
      Width, Height : X_Lib.Dimension;
   begin
      Argl := Null_Arg_List;
      Append_Get (Argl, Xm_N_Width, Width);
      Append_Get (Argl, Xm_N_Height, Height);
      Xt_Get_Values (The_Draw, Argl);

      Output.Put_Line ("Resize_CB called, new size: " &
                            X_Lib.Dimension'Image (Width) & " x " &
			    X_Lib.Dimension'Image (Height));
      if Task_Counter.Current_Value > 0 then
         Stop_Calculation;
      end if;
      X_Lib.X_Free_Pixmap (Display, Pixmap);
      Pixmap := X_Lib.X_Create_Pixmap (Display,
                          X_Lib.X_Root_Window_Of_Screen (Screen),
                          Width, Height,
                          X_Lib.X_Default_Depth_Of_Screen (Screen));
      Set_Size (Width, Height);
      --  I prefer to have my windows resized with the contents visible
      --  this leads to very frequent repaints. So don't automatically repaint
      --
--      Start_Calculation;
   end Resize_CB;


end Mandel_Global;