Use several DLL instances

Started by ale870, November 15, 2008, 03:17:02 AM

Previous topic - Next topic

ale870

Hi,



I wish to load several DLL instances of the same "newlisp.dll" in order to create several insulated environments. Even if I could use CONTEXT it is not the best way, since the script could change the context creating some seriuos errors.



I'm working in Pure Basic and I tried this:


OpenLibrary(0, "newlisp.dll")
OpenLibrary(1, "newlisp.dll")

Debug "Set:" + PeekS(CallFunction(0, "newlispEvalStr", @"(setq a1 100)"))
Debug "Get 1:" + PeekS(CallFunction(0, "newlispEvalStr", @"a1"))

Debug "Get 2:" + PeekS(CallFunction(1, "newlispEvalStr", @"a1"))

CloseLibrary(1)
CloseLibrary(0)


As you can see I opened twice the same DLL, and I associated it to id 1 and 2.

But when I execute I obtain:


Set:100
Get 1:100
Get 2:100



As you can see, the "GET 2:" return me the value "100" that I set in the first DLL call (id:1). It means windows, even if I opened the same dll in two different places, it uses the same working area.



Can you give me some hints/suggestions to avoid this problem?



Thank you!
--

ale870

#1
I made some tests and...

I tried a trick: make a copy of newlisp.dll (newlisp2.dll) but it seems the second copy does NOT work.

I friend of mine made the same test with another dll and it works...



So the "problem" seems related to newlisp.dll



Is there anything related to that library if loaded more than once?
--

newdep

#2
Yes that is correct.. ircc.. ;-)



Internaly the Library is known to PB when you open it in the same segment..

If you rename it or what ever doesnt matter..



You can only use twice the same library if you fork inside PB the loading of

the library's and then communicate internaly between the two sessions...

(but i never tried this in PB)



The same would happen if you would open twice another i.e. Libc...



But why would you like to open twice the same library?
-- (define? (Cornflakes))

Lutz

#3
Quoteeven if I opened the same dll in two different places, it uses the same working area.


This is only true if you open frome the same parent process.



If you have runnning two parent processes, then both will create separate workspaces for that DLL.

ale870

#4
Fork? So creating subprocess?

I will try to work in thread (even if a thread (win) is so much different from processes (unix).



I need to create two environments because I need to create a working environment, then I need to create a "test" environemnt (clean and independent from the first one).



I'm creating a game framework, and I want to create for the final users two environments for "production" and for "test", clean and separated (they do not need to communicate).
--

ale870

#5
Nothing.

Threads do not work.

And processes is not feasible under windows (no "fork" exists).

I will try another way (I will try to force CONTEXT usages in order to separate environments).



Thank you
--

newdep

#6
what about creating the main program and during startup extract the sub-program from the main-program actualy youre unzipping/unpacking it from the parent and executing it.. You could use "RunProgram" on a

Purebasic Memory segment..(the place where your second program is stored)..
-- (define? (Cornflakes))

ale870

#7
It could be a (bad) solution. In fact in that case I would have create a full communication protocol, plus some other checks to verify if a process crash... huge work.

Using fork could be a great solution but Window does not support fork :-(
--

Lutz

#8
You don't need fork. You could start two newlisp processes. Not the DLL, but two running newLISPs listening on pipes executing commands.



A second possibility is, two run two newlisp servers:



newlisp -c -d 10000

newlisp -c -d 10001



they listen then on the ports just like on the newLISP command line. You then send via TCP/IP line-feed terminated newLISP expressions. And listen back for the result.



Try staring a newLISP server and then use telnet to talk to it to see how it would work for your Basic app.



This is exactly the way the Java based IDE communicates with newLISP. Think of the Java IDE beeing your Basic application.



May be the first alternative using pipes, will have a higher through-put.

ale870

#9
Interesting possibility! Even if I knew about its existence, I didn't think to that solution.

I will investigate both solutions, since for me performance are a key-feature (but I could make a working environment using a dll, then create a newlisp independent server for testing purposes only! This could be a very good solution!)



Thank you for your suggestion!
--

newdep

#10
dont forget ..PB must do GUIevents and Networking in threads..

..else you wont be Async and that would be a shame for your project..



..I have that networking solution somewhere on the shelfs with PB and

newlisp doing 2D drawings in threads.. Ill see if i can find it..
-- (define? (Cornflakes))

ale870

#11
Thank you for your suggestions, but I already considerred it.

About 3D, I'm using PureGDK, and for GUI I will detect events either using callback (setCallback) and using non-bloking event checking.

That is mandatory for me, since I need, at the same time, render the 3D scene (done using a thread!).



Thank you!
--

newdep

#12
here a pre alpha release from 2 years ago...it did build it to a full

version but can find the source..hehe...disk craches etc.. ;-)





;------------------------------------------------------------------------------------------------
;; version 1.0 PB linux Beta 4
;; UDP wall, displays all info from UDP port 8080 on an Image-Wall
;; to create more output then forward all your udp ports to 8080 ;-)
;;------------------------------------------------------------------------------------------------

;;------------------------------------------------------------------------------------------------
;;globals
;;------------------------------------------------------------------------------------------------
Global port = 8080
Global T.s
Global C.s
Global true = 1
Global false = 0

;;------------------------------------------------------------------------------------------------
;; console init
;;------------------------------------------------------------------------------------------------
OpenConsole()


;;------------------------------------------------------------------------------------------------
;; check desktop
;;------------------------------------------------------------------------------------------------
If ExamineDesktops()
  Global dw = DesktopWidth(0)
  Global dh = DesktopHeight(0)
  Global dd = DesktopDepth(0)
  Global df = DesktopFrequency(0)
  Global dn.s = DesktopName(0)
EndIf

;;------------------------------------------------------------------------------------------------
;; create image of dw - 10 x400
;;------------------------------------------------------------------------------------------------


;;------------------------------------------------------------------------------------------------
;;check network
;;------------------------------------------------------------------------------------------------
PrintN("udpGUI: Running")
If InitNetwork() = 0 : PrintN("No network available!") : End : EndIf
If CreateNetworkServer(0,port,#PB_Network_UDP) = 0 : PrintN("Cant bind to "+Str(port)+" !") :  End : EndIf

;;------------------------------------------------------------------------------------------------
;;create update image
;;------------------------------------------------------------------------------------------------
Procedure _pixel(x.w, y.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Plot(x,y)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _square(x.w, y.w, w.w, h.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Box(x,y,w,h)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _circle(x.w, y.w, r.w)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    Circle(x,y,r)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure

Procedure _text(x.w, y.w, t.s)
    StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Transparent)
    BackColor(RGB(Random(255),Random(255),Random(255)))
    FrontColor(RGB(Random(255),Random(255),Random(255)))
    DrawText(x,y,t)
    StopDrawing()
    SetGadgetState(0, ImageID(0))
EndProcedure
;;------------------------------------------------------------------------------------------------
;;network UDP thread
;;------------------------------------------------------------------------------------------------
Procedure listener()
Repeat
   Delay(1)
   server_event = NetworkServerEvent()
    If server_event
            client = EventClient()
            Select server_event

                        Case #PB_NetworkEvent_Data
                                *buffer = AllocateMemory(65)
                                    If ReceiveNetworkData(client, *buffer, 64)
                                        T = PeekS(*buffer)
                                        T = LTrim(T)
                                        T = RTrim(T)
                                        T = LCase(T)
                                    EndIf
                                 FreeMemory(*buffer)

                               C= IPString(GetClientIP(client)) + ":" + Str(GetClientPort(client))
                               CloseNetworkConnection(client)
            EndSelect
    EndIf
Until quit = 1
EndProcedure

udpT = CreateThread(@listener(), 1)
If udpT = 0 : PrintN("Error creating thread!") : End : EndIf


;;------------------------------------------------------------------------------------------------
;; main window
;;------------------------------------------------------------------------------------------------
If OpenWindow(0, 0, 0, 0, 0, "udpGUIl", #PB_Window_Invisible |#PB_Window_MinimizeGadget| #PB_Window_MaximizeGadget|#PB_Window_Maximize )
    CreateGadgetList(WindowID(0))

Repeat
        ;Delay(1)
         EventID = WaitWindowEvent(100)

              ;; init a new window  hide it create an image on it
              If StringField(T, 1, " ") = "init" And init = false
                                        ResizeWindow(0,Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")))
                                        HideWindow(0, 0)
                                        SetWindowTitle(0,StringField(T, 6, " "))
                                        ImageGadget(0, 0, 0, Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")) , ImageID(0))
                                        CreateImage(0, Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")) , #PB_Image_DisplayFormat )
                                        init = true;

             ElseIf  init = true
                                        ;; pixel x y
                                        If       StringField(T, 1, " ") = "pixel"
                                                _pixel(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")))

                                        ;; box x y w h
                                        ElseIf StringField(T, 1, " ") = "square"
                                                _square(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")),Val(StringField(T, 5, " ")))

                                        ;; circle x y r
                                        ElseIf StringField(T, 1, " ") = "circle"
                                                _circle(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")),Val(StringField(T, 4, " ")))

                                       ;; text x y text
                                       ElseIf StringField(T, 1, " ") = "text"
                                                _text(Val(StringField(T, 2, " ")), Val(StringField(T, 3, " ")), LTrim(RemoveString(T,Left(T,FindString(T,StringField(T, 4, " "),1) - 1  ))))

                                      ;; hides the window
                                      ElseIf StringField(T, 1, " ") = "hide"
                                                 HideWindow(0, 1)

                                       ;; shows the window
                                       ElseIf StringField(T, 1, " ") = "show"
                                                 HideWindow(0, 0)

                                       ;; make window sticky on top of all
                                       ElseIf StringField(T, 1, " ") = "wett"
                                                 StickyWindow(0, 1)

                                       ;; make window dray, normal behavior
                                       ElseIf StringField(T, 1, " ") = "dry"
                                                 StickyWindow(0, 0)

                                       ElseIf StringField(T, 1, " ") = "clean"
                                                w = ImageWidth(0)
                                                h = ImageHeight(0)
                                                FreeImage(0)
                                                CreateImage(0, w, h , #PB_Image_DisplayFormat )

                                       ;; close all
                                       ElseIf StringField(T, 1, " ") = "close"
                                                quit = true

                                       EndIf
                EndIf

        T = ""
        Until EventID = #PB_Event_CloseWindow  Or quit = true
EndIf

KillThread(udpT)
CloseNetworkServer(0)
CloseConsole()
End


-- (define? (Cornflakes))

ale870

#13
Thank you!

I will study it!
--

ale870

#14
Quote from: "Lutz"You don't need fork. You could start two newlisp processes. Not the DLL, but two running newLISPs listening on pipes executing commands.



A second possibility is, two run two newlisp servers:



newlisp -c -d 10000

newlisp -c -d 10001



they listen then on the ports just like on the newLISP command line. You then send via TCP/IP line-feed terminated newLISP expressions. And listen back for the result.



Try staring a newLISP server and then use telnet to talk to it to see how it would work for your Basic app.



This is exactly the way the Java based IDE communicates with newLISP. Think of the Java IDE beeing your Basic application.



May be the first alternative using pipes, will have a higher through-put.


After some tests using DLL, I decided to try pipe method.

Results are simply incredible! newLisp pipe is great!



I made two tests: first test using a single thread, and another test using 10 (ten!) threads running together, to solve the same problem.



I have a Dual quad core CPU (we can say they are "almost" 4 CPU), Windows Vista and 4Gb Ram.



It's incredible:



Single thread took about 25 seconds.

Multithread took about 11 seconds!!!



It means that using multiprocessors (newlisp -c) called ten times (10 newLisp interpreters running all together!), PB, newLisp and Windows Vista can use multicore in an effective way (not only words... but facts! Multi-CPU is really running!).



Furthermore consider that single thread my CPUs were busy at about 35%, but using ten threads they were busy always to 100% !!!



I definitively use this method to implement my game framework using newLisp ;-)



Thank you!
--