Search This Blog

Monday, February 7, 2011

Using Threads in Visual Basic

Threads in Visual Basic are not commonly used because of complexity. In a 32 bit Windows environment (talking about Windows 95/98/NT) it has become a necessity to use more than one thread for each process. But is it true that creating threads in Visual Basic is tough? Not really! Visual Basic has its own feature of simplifying Windows 32 bit API calls. Think about a long backup procedure, which needs to be intervened in case the user wants to suspend or stop the backup procedure. If you have not implemented a separate thread for this copy purpose, you will not be able to stop the process until and unless you kill the process forcefully or you restart your machine (Windows 95 non-OEM versions might show endless blue screens). This is not a good idea for a professional grade application. Therefore let us talk about creating threads.
We will look at creating free threading model (and not apartment model of threading) in Visual Basic using the 'CreateThread' Win32 API call. Those who are familiar with creating Win32 applications using Visual C++, will be able to recognize this little function which helps in creating a new thread within a process very easily. In Visual Basic, it is also pretty easy to create a thread. I will take a look at the example code ExCopy (which is supplied with this article). This code is used to break a long file into several small 3¼-inch high-density floppy disks (similar to what you see in WinZip utility). An independent thread handles the copy process. Therefore you can see that during the copy process, you can easily move the ExCopy window.

How the thread is created:
Let us have a look at the following function written in the example code…

'Thread creation helper function
Public Function StartCopy(clsObject As clsExCopy)
    Dim NewThreadID As Long
    Dim Threadhandle As Long
    Dim Param As Long

    ' Free threaded approach
    Param = ObjPtr(clsObject)

    'Create a thread with no security attribute but
    'with default stack size and default creation flag
    Threadhandle = CreateThread(0,_
        0, _
        AddressOf ThreadFunction, _
        Param, _
        0, _

    If Threadhandle = 0 Then
        ' Return with zero (error)
        Debug.Print "Unable to create the free thread"
        Exit Function
    End If

    ' We don't need the thread handle
    CloseHandle Threadhandle

    'Return the created ID
    StartCopy = NewThreadID
End Function

This public function is used to create the thread. StartCopy takes only one parameter of clsExCopy type. The class clsExCopy is defined in the ExCopyFile_IO.cls module. This class is used to copy data to the disks. You should call the StartCopy function with a valid clsExCopy class object. For example you might want to call this function when the user clicks on 'Start' button…

Private Sub StartBtn_Click()
    'Create a new Thread object
    If ExCopyObj Is Nothing Then
        Set ExCopyObj = New clsExCopy
        Set ExCopyObj = Nothing
        Set ExCopyObj = New clsExCopy
    End If

    ExCopyObj.bStopNow = False

    'Create a new thread
    StartCopy ExCopyObj

    'Can not click on Start now
    StartBtn.Enabled = False
End Sub

Therefore you are passing an object value to the StartCopy function. In this function the Win32 API CreateThread function is used to create a new thread.
Now take a closer look at the call to this function.
The first parameter is actually a pointer to the SECURITY_ATTRIBUTE structure. We are passing zero to avoid any security feature.
The second parameter is used to represent the stack size of the newly created thread. We are passing zero to let Windows Kernel determine the stack value.
The CreateThread function uses the third parameter as a function pointer, which it calls when the thread is created. The third parameter uses the 'AddressOf' unary operator which returns the pointer to a function (acceptable by the API). Therefore AddressOf ThreadFunction will return the actual pointer to the function 'ThreadFunction' which does the Win32 API very well accept.
The fourth parameter is used as a pointer to the arguments passed to the function mentioned in third parameter. Visual Basic has a function ObjPtr which returns the pointer to memory object which I have used to pass as a parameter to the function ThreadFunction.
The fifth parameter is used to specify how you want the thread to behave. For example you may set the thread priority of a particular thread to a higher value by specifying THREAD_PRIORITY_ABOVE_NORMAL to this parameter. This is a bit field where several options can be OR-ed.
The CreateThread function returns the thread identification value in the sixth and the final parameter.
The StartCopy function returns the handle of the thread which you can destroy using the CloseHandle Win32 API call after the thread is successfully created. Destroying this handle does not destroy the thread. This merely frees the handle associated with that thread.
The CreateThread function returns immediately after it creates the thread. The newly created thread runs as an independent thread.
As you have noticed that we have passed a pointer the function ThreadFunction to the third parameter of CreateThread function, let us see what it looks like…

'The thread entry point
Public Function ThreadFunction(ByVal Param As IUnknown) As Long
    Dim clsObject As clsExCopy
    ' Free threaded approach
    Set clsObject = Param
End Function

Pretty small, isn't it? ThreadFunction is used to call a method (ExCopy in this case) from the clsExCopy class. This function accepts parameters as IUnknown which represents the basic interface supported by Visual Basic COM layer. The value from this parameter is copied to a clsExCopy class object. Remember that once you go out of this function, the thread is destroyed.
This is all about creating multiple threads in Visual Basic. Remember to create the project as 'ActiveX EXE'. The rest of the example code deals with form controls and the copy technique (in clsExCopy). This way of creating a thread is called 'Free Threading', which is not supported by Visual Basic COM/DCOM layer. Visual Basic COM/DCOM uses either 'Single Threading' model or 'Apartment model' threading. But free threading models are very fast compared to Apartment model threading which uses marshalling technique to transport data between two objects. Anyway we will discuss about this approach later.

Article by:
Samit Ray
Price Waterhouse Associates (P) Ltd.

BSP Trees

This article explains how BSP (binary space partitioning) trees can be used in
a game such as DOOM as part of the rendering pipeline to perform back-face
culling, partial Z-ordering and hidden surface removal.
To explain the use of BSP trees, it is best to start with an example. Consider
a very simple DOOM level.
  |  |                                                                    |  |
  |  |                                            y                       |  |
  d1 |                                                                    |  b1
  |  |                               f'                                   |  |
  |  |                                                                    |  |
     |          C--------------------f-----------------------D            |
  |  |          |                                            |            |  |
  |  |          |                    f"                      |            |  |
  |  d          |                                            |            b  |
  |  |          |                                            |            |  |
  |  |       e" e  e'                                     g' g  g"        |  |
  d2 |          |                                            |            |  b2
  |  |          |                                            |            |  |
  |  |          |                                            |            |  |
  |  |          E                                            F            |  |
  |  |                              x                                     |  |
  |  |                                                                    |  |
      ----c1---- ----------------------c2-------------------- -----c3-----
The level consists of a room within a room. The player cannot go outside of the
area within the square ABHG.
First some definitions (sorry :-)
The _vertices_ are marked A-H, the _faces_ are marked a-g.
We define a _line_ by using an ordered pair of vertices, so that
      a = (A,B)  e = (E,C)  f = (C,D)  g = (F,D)
We say a point is to the _left_ of a line if it is to the left of the vector
between its two vertices, taken in order.
So, in the above example, nothing is to the left of line a; everything is to
the right of it. Note that this depends upon our definition of line a, and if
we had defined a = (B,A) then everything would be to the left of line a.
A _face_ is a side of a line which is visible to the player. Wall e above, for
example, has two faces (marked e' and e"). Not all walls have two faces - if
the player can never see one side of a wall it only has one.
A face is fully defined by an ordered pair of vertices and an ordered pair of
faces - a left face and a right face.
The BSP tree for the example above might look like this:
                    / \
                   /   \
                  /     \
           a,d1,b1       e
                        / \
                       /   \
                      /     \
                 d2,c1       g
                            / \
                           /   \
                          /     \
                        c2       c3,b2
Each node contains a line. Everything to the left of that line is in the left
subtree, and everything to the right of that line is in the right subtree.
Note that face d is neither completely to the right of nor to the left of face
f. To accommodate this, we split it up into two halves, and put one half into
the left subtree and one half into the right subtree. Thus, we have to generate
new faces in order to build the BSP tree.
I will explain how the BSP tree is created later. Firstly, I will give the
algorithm used to render a picture using the tree.
Suppose the player is standing at position 'x', and looking North.
We start at the top of the tree at line f. We are standing to the right of line
f, so we go down the LEFT of the tree. This is because we want the furthest
polygons first.
We come to the left-hand-most terminating node. We write down the faces here
in our notepad. "a,d1,b1".
Since we've come to a terminator, we back up a level. Back to the top, but we
have to go down the right subtree yet. Firstly, though, we look at face f - the
deciding face for this node. We've got everything behind it in our list, we've
yet to look at anything in front of it, but we must put it into our list.
Note that face f has two sides - f' and f". Since we already know we're on the
right of line f, we know that we can only see its right side - so we write
f" in our notepad. It now says a,d1,b1,f".
Note, though, that if we were looking south (i.e. our line-of-sight vector
points away from face f) then we could not see either face f or anything on
the other side of face f - in this case, we just don't bother going any further
down the tree.
Now we go down the subtree and come to node e. We are on the right of e, so we
go down the left subtree and get a terminal node - we just write d2,c1 in our
Back up, decide on which side of e to put in. We decide e'. The notepad now
says a,d1,b1,f",d2,c1,e'.
Down the right subtree to node g. We're on the left, so down the right subtree
to c3,b2, up, check g (we're on the left = g'), back down to the final node,
get c2, up, up, up, and we're done.
The notepad ends up saying:
a d1 b1 f" d2 c1 e' c3 b2 g' c2
If we draw these walls, in this order, then we will get the correct scene. I
would recommend using a one-dimensional Z-buffer to get finer granularity than
the painter's algorithm provides, before plotting the walls. Note also that
some walls are behind you - however, since you need to calculate their z
coordinates for the perspective transform, you can merely discard faces with
negative z values.
Creating the BSP tree
The BSP tree almost creates itself. The only difficulty is knowing when to stop
recursing. Notice that the terminal nodes are just put into the list - so a
sufficient condition for a group of faces to form a terminal node is that they
can be drawn in a set order without any mistakes occurring in the drawing. That
is, if wherever the player can stand, the group of walls will never obscure
each other.
So let us begin: Choose face f (the choice is fairly arbitrary - it is best
to choose faces which don't split many other faces up. However, in this case
it is unavoidable). Split up faces d and b, because they straddle the line f.
(The line you are splitting along is known as the _nodeline_ in DOOM-speak).
Then put everything to the left of f in the left subtree, and vice-versa:
                           / \
                          /   \
                         /     \
                  a,d1,b1       b2,c,d2,e,g
We can terminate the left node - because walls a,d1 and b1 form a convex
shape, they can never overlap each other from any point of view. However, on
the other side, face e can obscure face d2 from certain viewpoints (our example
viewpoint above, for one) so we divide along side e. This causes side c to be
split, but side a is not split because it's not in our current list of sides.
The next level is:
                           / \
                          /   \
                         /     \
                  a,d1,b1       e
                               / \
                              /   \
                             /     \
                        d2,c1       b2,c2,g
Now, c1 and d2 never overlap, so we have another terminal node. We next divide
along line g, splitting c2 into c2 and c3, and the last nodes are terminals
(a node with one face in is always terminal :-).
This is the basic idea behind a BSP tree - to give an example how effective it
is, consider standing at point y and looking North. Because you're looking
away from face f, you don't bother recursing down the entire left subtree. This
then very quickly gives you the ordered list of faces: a,d1,b1.
If at each node we define a bounding box for each subtree, such that every line
in a subtree is contained by its corresponding bounding box, then we can cut
some invisible polygons (ones which lie to the left or right of the screen) out
by comparing each bounding box with the cone of vision - if they don't
intersect, then you don't go down the whole subtree. DOOM does this, allowing
it to store an *entire* level in one huge BSP tree.
Here's some pseudo-code to traverse the tree. The function left() returns TRUE
if the second input vector is to the left of the first input vector. This is
a simple dot product, and by pre-calculating the slope of the nodeline can be
done with one multiply and one subtract.
vector  player                         ; player's map position
vector  left_sightline                 ; vector representing a ray cast through
                                       ; the left-most pixel of the screen
vector  right_sightline                ; the right-most pixel of the screen
structure node
  vector vertex1
  vector vertex2
  node   left_subtree
  node   right_subtree
  face   left_face
  face   right_face
  box    bounding_box
  bool   terminal_node
  face   terminal_node_faces[lots]
recurse(node input)
if (cone defined by left and right sightlines does not intersect the node's
    bounding box)
if node.terminal_node
  ; terminal node - add faces to list
if left(vertex2-vertex1,player-vertex1)
  ; player is to the left of the nodeline
  if not left(vertex2-vertex1,right_sightline)
    ; sight points right - we are looking at the face
  ; now go down the left subtree
  ; player is to the right of the nodeline
  if left(vertex2-vertex1,left_sightline)
    ; sight points left - we are looking at the face
  ; now go down the right subtree
end recurse
This isn't anywhere near a decent implementation - the data structures, for
example, leave a *lot* to be desired :-)
It should be possible to encode all the functions inline; in fact, it would be
feasible to take a BSP tree and hard-code it into some run-time generated code
which you just call to recurse the tree ... but I'm just a hacker at heart ;-)
Anyway, I hope this helps answer some peoples' questions on this subject. If
you have any more questions, please don't hesitate to email me.
Catch you later,
Eddie xxx
Official Archimedes convertor of : Hear and remember, see and understand,
Wolfenstein 3D and proud of it!! : do and forget.
=================================: Something like that, anyway.         ==========================================

Let Us 'C'

struct Indian_female_professionals { 
    double styles;
    short skirts;
    long time_to_understand_problems;
    float mind;
    void knowledge;
    char non_co-operative;
struct married_females {
    double weight;
    short tempered;
    long gossip;
    float hopes;
    void word;
    char unstable;
struct engaged_females {
    double time_on_phone;
    short attention_on_work;
    long boast;
    float on_cloud_nine;
    void understanding;
    char edgy;
struct newly_married_females {
    double dinner_invitation;
    short time_at_work;
    long lunch_break;
    void bank_balance;
    char hen_pecked;
struct Indian_husband_wife_professionals {
    double income;
    short tempered;
    long time_no_see_each_other;
    void love_life;
    char money_making;

MacOS X on regular Intel compatible hardware

I think MacOS X running on regular Intel hardware is a great idea. Just think about the kind of interoperability that would offer. I guess I am biased because I think from the developer's point of view (being a developer myself). If MacOS X is able to run on regular Intel compatible hardware, then it can become as popular as Windows is today. And that would give developer motivation to write the same software the write for Windows. Just think about it. Today the best games come for the Windows platform first and then they are PORTED to the Mac. Now, since the Mac is using regular Intel compatible hardware, developers can target both platforms at the same time. Besides if MacOS X runs for regular Intel chips it also means it would run on those sexy AMD chips (which I am a great fan of). Compare to those many OSes out there, the MacOS X really stands out. Take a look. UNIX like core (Darwin), stability, features, performance, looks, it has it all. Not many people can afford the costly (albeit great) Mac hardware. So this would be a real big thing. If I were to rate all those Desktop OSes out there, my rating would go like this (earlier the better): 1. Windows 7, 2. MacOSX, 3. Haiku, 4. ReactOS. Sorry I am not a Linux fan due to the bitter experience I had with it and lack of standardization.

Edit: This post was written nearly 5+ years ago and was moved over from Windows Live Spaces to here.