Back

Understanding RAII

In this tutorial we will explore one way that fundamental OO principles can be efficiently and easily applied using FreeBASIC. The principle we'll be discussing is called RAII. That stands for "Resource Acquisition Is Initialization."

Now that probably seems pretty nerdy or like whaaat if you don't know much about programming. What it's saying is that, when you make a variable, the variable gets some kind of resource that it needs, and when the variable dies, it releases that resource.

A file would be one example of a resource an object might acquire, do its operation with the file, and then release the file as the variable is released. As you use the file, you might notice an area where you have to abort for some error. Well in this case, you'd make sure to close the file, and then jump to safety, right? Wrong! With RAII all of that is done for you automatically.

Let's look at it in an abstract way. We make an object. This object's prototype might look like this:

type FILE_READER
	file_handle as integer
	
	declare constructor( byref filename as string  )
	declare destructor( )
	
	declare function get_num_of_records( ) as integer
	declare function get_record( byval which_record as integer ) as RECORD ptr
end type

Now, remembering what I said before about acquiring and releasing, here's how the constructor and destructor will work:

constructor FILE_READER( byref filename as string  )
	file_handle = freefile
	open( filename, for binary, as file_handle )
end constructor

destructor FILE_READER( )
	close( file_handle )
end destructor

Now, this object has a nice routine for us to pull data out of the opened file. It's giving us back records of sales clients. One of those clients needs to be called because there's a delay in the airport near San Juan, their area of operations. The guy that coded the original system wasn't too bright, so we have to look through each record in a loop and get the number. Luckily this is a tiny company and these people have MAYBE 4 customers. :)

So, we'll code a sub that'll print out all the customers for us. Real men run programs from command prompts, so we won't worry about using sleep. ;)

sub list_all_clients( )
	
	dim as FILE_READER my_reader = "clients.rec"
	
	dim as RECORD ptr a_client_record
	dim as integer records = my_reader.get_num_of_records( )
	
	'' loop through all those records...
	for i as integer = 0 to records-1
		
		'' our object gives us a record... how nice!
		a_client_record = my_reader.get_record( i )
		
		'' null pointer is bad this is unexpected!
		if( a_client_record = 0 ) then
			
			'' run away!
			exit sub
		end if
		
		print a_client_record->name, a_client_record->phone_number
		
	next
	
end sub

The main point I'm stressing here is that even when you encounter an unexpected fatal error that has no valid form of recovery, you can simply "exit sub" and escape the horror. That's because when the sub ends, no matter HOW it ends, your variable ends with it, meaning its destructor gets called. The file is closed. You can probably see how useful this would be for stuff, an extremely important application of RAII is when using mutex locks.

If you're familiar with threading, you know that if you take the lock and forget to release it, you've basically locked yourself out of the procedure from then on. Inevitably you will reach a deadlock, that means, everyone will be waiting for the lock that was never released. Bad!

Another similar application would be the screenlock/screenunlock functions in FreeBASIC. You can lock the screen and do some sweet fast über elite graphics stuff, but you better make sure to unlock it, otherwise the next time you try to get the lock, you'll find that it's already taken. What will your program do then? Kick its feet up, relax, and laugh at you. I intend to make the thing earn its keep.

Back
by cha0s