Archive for the 'Programming' Category

Sep 21 2008

wxMax on Ubuntu Linux: I give up

Published by Winni under Programming, Software

I’ve spent the last two days setting up virtual machines with VMWare Fusion 2 for Ubuntu 8.04.1 and Windows Vista Ultimate Edition, both in their 32 Bit flavors. The idea was to have build systems for cross platform BlitzMax development.

I wanted to build all the modules myself and not simply download and install the pre-built binaries, and I needed quite a lot of help from Bruce A. “Brucey” Henderson, the author of the BlitzMax port of wxWidgets, to get wxMax compiled and running on Vista. Microsoft’s latest OS requires some minor changes of the wxMax source code, but it now works and runs beautifully. This opens the door for serious cross platform application development in BlitzMax, at least between OS X and Windows. wxMax offers many more mature and sophisticated GUI widgets than MaxGUI does, and wxMax is object oriented from top to bottom, which is more as I like it.

But there is a third platform supported by BlitzMax and wxMax: The penguin OS, Linux.

Now why would I be interested in Linux? It’s rather simple: In the near future, I need to move to a new web server. My current server is a Linux box owned by a former colleague of mine who is now retiring and closing his business. I am using this as an opportunity to get my own (virtual) server with full root/administrator privileges, including the option to install my own binary software. You usually get better deals for Linux servers than for Windows Server machines, so I wanted to find out if I could use BlitzMax on Linux and thus gave the most popular Linux distribution, Ubuntu, a shot. Ubuntu is also the Linux distribution recommended by Blitz Research, and most web hosting companies offer Ubuntu-based servers.

So I’ve downloaded Ubuntu 8.04.1, created a VM for Ubuntu in VMWare Fusion and installed it. That part was a piece of cake. Fusion’s support for non-Windows XP operating systems is outstanding, while in Parallels Desktop (for which I also have a license) the OS would not even boot. Parallels is great for Windows XP, but for everything else, I suggest that you use VMWare Fusion.

After the OS was running and also had VMWare Tools installed, I’ve checked out the HEAD development revision of BlitzMax, Brucey’s modules and wxMax from their respective SVN repositories and also downloaded a source distribution of wxWidgets.

I then needed to download and install tons of additional stuff via apt-get and Ubuntu’s graphical package manager (when I didn’t know the exact names of the packages that I needed) until I was finally able to compile everything. If anybody wants to make Linux more end user friendly, here’s your first stop: Consolidate the damn platform and fix the annoying dependency issues! No user on the planet wants to mess around with crap like that!

When I tried to run one of the wxMax sample applications, I got this error:

/usr/bin/ld: warning: libstdc++.so.6, needed by /usr/bin/../lib/libcairo.so.2, may conflict with libstdc++.so.5
Fatal Error: Mismatch between the program and library build versions detected.
The library used 2.8 (no debug,Unicode,compiler with C++ ABI 1002,wx containers,compatible with 2.6),
and your program used 2.8 (no debug,Unicode,compiler with C++ ABI 102,wx containers,compatible with 2.6).
Aborted

It supposedly has something to do with different versions of gcc that have been used to build different parts of the packages. Now word has it that BlitzMax is built with gcc 3, so I went and made sure that all of my stuff was also built with that version of the GNU compiler. It didn’t help; the error remained.

After having wasted more than a day on this alone and although I had received a lot of support from Brucey and the BlitzMax community, I was not able to find a working solution and therefor I am now giving up.

Seeing that deployment on Linux obviously still is a nightmare, I drop the thought of getting myself a Linux server entirely. I do not want to run into the situation that I build something on my development system and then find out that it won’t run on my server.

As a teenager, I found the sort of problems that I’d been facing for the last one to two days interesting. But I’m 38 and nowadays expect things to work. I am no longer willing to waste my lifetime on crap like that.

Linux has failed me for the last time, as Darth Vader would phrase it.

No responses yet

Sep 15 2008

Multithreading in BlitzMax

Published by Winni under Programming

Finally!

The latest SVN versions of BlitzMax have some basic support for multi-threading.

The following sample code is a remake of the old Alaska Software Xbase++ ‘coffee’ sample application. I haven’t used Xbase++ in quite a few years now, so I had to rewrite it based upon what I could remember of the coffee sample. Basically, it is about ten programmers who drink coffee while they are working and when their cups run empty, they go to a coffee machine and get themselves a refill. When the coffee machine runs empty, too, the guy who needs coffee has to cook some fresh one first. I’ve added to this simple scenario a button that will ‘close the office’ for the day and send the developers home. Before they do that, they finish their coffees and return their cups. The last one to do so turns off the coffee machine.

This idea is implemented using ten worker threads, one for each developer. They share one resource, namely the coffee machine. The purpose of the sample is to demonstrate mutexes as a means of synchronizing access to shared resources by concurrently running threads. As you probably already know, not synchronizing the access to shared resources is a perfect way to crash your application and giving you a hell of time to find the bug.

Here is the code, written on OS X, but it also works on Windows:

Download an application bundle for Mac OS X/Intel.

Download an application bundle for Mac OS X/PPC.

Download an executable for Windows.

I’ve begun to implement a thread class for BlitzMax. You can download it from here.

'GUI Coffee, Inc.
SuperStrict

'Put something on the screen.

Import MaxGui.Drivers
Import MaxGui.CocoaMaxGui
Import Pub.Threads
Import BRL.Random
Import BRL.Event
Import BRL.Eventqueue

AppTitle = "Coffee, Inc."

Global x:Int = 0
Global y:Int = 0
Global width:Int = 640
Global height:Int = 480

Global AppWindow:TGadget = CreateWindow (AppTitle, x, y, width, height)

Global fileMenu:TGadget = CreateMenu ("&File", 0, WindowMenu (AppWindow))
Global xit:TGadget = CreateMenu ("E&xit", 1, fileMenu)

Global helpMenu:TGadget = CreateMenu ("&Help", 2, WindowMenu (AppWindow))
Global about:TGadget = CreateMenu ("&About...", 3, helpMenu)

UpdateWindowMenu AppWindow

Global devStatus:TGadget[10]

For Local n:Int = 0 To 9
	devStatus[n] = CreateTextField (4, 4 + n*30, ClientWidth (AppWindow) - 8, 24, AppWindow)
Next

Global goHome:TGadget = CreateButton ("Go home, guys!", 240, 400, 140, 24, AppWindow, BUTTON_OK)

'Setup the office environment.

Const cupSize:Int = 200

'Your simple Italian coffee machine. One load is good for eight cups.
Type CoffeeMachine

	Field hasCups:Int = 10
	Field hasCoffee:Int
	Field isCooking:Int
	Field myMutex:Int

	Method Create()
		hasCoffee = 0
		myMutex = CreateMutex()
	End Method

	Method giveCoffee:Int( name: String, nPos:Int )
		LockMutex( myMutex )
		If hasCoffee <= 0
			Local boiler:String = ""
			For Local n:Int = 1 To 8
				boiler :+ "+++"
				SetGadgetText( devStatus[nPos], name + " is cooking fresh coffee: " + boiler )
				Delay 300
			Next
			hasCoffee = 8 * cupSize
		End If
		SetGadgetText( devStatus[nPos], name + " takes coffee." )
		hasCoffee :- cupSize
		Delay 750
		UnlockMutex( myMutex )
		Return cupSize
	End Method

	Method giveCup( name: String, nPos:Int )
		LockMutex( myMutex )
		SetGadgetText( devStatus[nPos], name + " takes a cup.")
		hasCups :- 1
		Delay 400
		UnlockMutex( myMutex )
	End Method		

	Method returnCup( name: String, nPos:Int )
		LockMutex( myMutex )
		SetGadgetText( devStatus[nPos], name + " returns his cup to the kitchen.")
		hasCups :+ 1
		Delay 1000
		If hasCups = 10
			SetGadgetText( devStatus[nPos], name + " is last, he turns off the coffee machine.")
			Delay 3000
			HideGadget( goHome )
		End If
		UnlockMutex( myMutex )
	End Method

End Type

'A very simple software developer. He only works as long as he has coffee.
Type Developer
	Field Name:String
	Field Position:Int
	Field hasCoffee:Int
	Field machine:CoffeeMachine
	Global EOB:Int = False

	Method Create:Developer( name:String, pos:Int, machine:CoffeeMachine )
		Self.Name = name
		Self.Position = pos
		Self.hasCoffee = 0
		Self.machine = machine
		Return Self
	End Method

	Function SignalEOB()
		SetGadgetText( goHome, "Office is closing!" )
		DisableGadget( goHome )
		EOB = True
	End Function

	Method Working()
		machine.giveCup( name, Position )
		Repeat
			hasCoffee :- Rand(1, Int(cupSize/4) )
			If hasCoffee <= 0
				SetGadgetText( devStatus[Position], name + " needs coffee !!!")
				hasCoffee = machine.GiveCoffee( name, Position )
			Else
				Local cupContents:String = ""
				For Local n:Int = 1 To Int( 1 + hasCoffee/10)
					cupContents :+ "#"
				Next
				SetGadgetText( devStatus[Position], name + " is happily working. Coffee left: " + cupContents + " ( " + hasCoffee + " ml)." )
			End If
			Delay 600
		Until EOB
		machine.returnCup( name, Position )
		SetGadgetText( devStatus[Position], name + " went home.")
	End Method
End Type

'The thread factory
Function BuildThread:Object( data:Object)
	Local myDev:Developer = Developer(data)
	myDev.Working()
End Function

'Start the coffee machine
Global Luigi:CoffeeMachine = New CoffeeMachine
Luigi.Create()

'Get the guys to work
Global DevTeam:Developer[10]
Global devName:String[] = [ "Mark", ..
							"Brucey", ..
							"Skidracer", ..
							"SebHoll", ..
							"SimonH", ..
							"SimonA", ..
							"FlameDuck", ..
							"MarkT", ..
							"RobH", ..
							"Woz"]

For Local n:Int = 0 To 9
	DevTeam[n] = New Developer
	DevTeam[n].Create( devName[n], n, Luigi )
Next

'Ready, steady, go!
Global handles:Int[10]

For Local n:Int = 0 To 9
	handles[n]=CreateThread( BuildThread,  Object(DevTeam[n]) )
Next

'Send the boys home
Function ShutDown()
	Developer.SignalEOB()
	For Local n:Int = 0 To 9
		DetachThread( handles[n] )
	Next
End Function

'Your good old fashioned GUI event loop
Repeat
	Select WaitEvent ()
		Case EVENT_GADGETACTION
			If (EventSource () = goHome)
				ShutDown()
			End If 

		Case EVENT_WINDOWCLOSE
			ShutDown()
			End

		Case EVENT_MENUACTION
			If EventData () = 1 Then
				ShutDown()
				End
			End If

			If EventData () = 3 Then Notify ("Coffee, Inc. only works with coffee!")

	End Select
Forever

6 responses so far

« Prev - Next »