News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

How fill structure in data block?

Started by bomz, July 01, 2011, 08:34:33 PM

Previous topic - Next topic

qWord

it is simple: make all variables and structures local - then it is clearly thread save. By doing this, you application will also benefits from the fact, that the current stackspace/location is properly completely hold in the cache.
FPU in a trice: SmplMath
It's that simple!

bomz

if I do all variables local I must fill it fully including zero's it need about 50 strings of code

qWord

Quote from: bomz on July 01, 2011, 10:12:13 PM
if I do all variables local I must fill it fully including zero's it need about 50 strings of code
if thread save code is needed, then you must do it.
FPU in a trice: SmplMath
It's that simple!

jj2007

Quote from: bomz on July 01, 2011, 10:12:13 PM
if I do all variables local I must fill it fully including zero's it need about 50 strings of code

Yes, but you could have a 'template' in .data from which you copy your stuff into the locals. Watch the order, though. By the way, I can't quite see the point why code must be thread-safe all the time. Only on very rare occasions would I start a separate thread using the same data structures in parallel.

bomz

if you need two threads you need have local data for each. this structeres which I move to data use only in one place and each time call it they begin FILL

bomz

in this program with ListBox I am many times in different places of code put/get data from list view and each time begin

mov lvi.imask,LVIF_TEXT+LVIF_PARAM
mov lvi.iItem, esi
mov lvi.iSubItem,0
lea eax, buffer
mov lvi.pszText, eax
mov lvi.lParam, esi
invoke SendMessage, hList, LVM_INSERTITEM, 0, addr lvi


this is the half of code. and I want to all such places make it own variable and fill it in data

qWord

Quote from: jj2007 on July 01, 2011, 10:31:45 PMI can't quite see the point why code must be thread-safe all the time.
It must not be thread save all the time - only when needed  :wink
However, generally it is an good approach to create only thread save code (IMO) - especially when writing libraries/DLLs.
BTW jj: is MasmBasic thread save?
FPU in a trice: SmplMath
It's that simple!

bomz

else - to exlude the conflict between diferent places of code which may read/write listview, I need do many proc's with it's own local LVI buffer - this need push/pop call/back.....

jj2007

Quote from: qWord on July 01, 2011, 10:42:50 PM
BTW jj: is MasmBasic thread save?

If you know what you are doing, sure. But it uses lots of global variables, of course. For example, if you create two threads that write in parallel to the console, you'll be in trouble... how do you use parallel threads?

dedndave

not all data needs to be local
generally, it is only the variables that are written to that can cause trouble

qWord

Quote from: jj2007 on July 02, 2011, 05:45:29 AMIf you know what you are doing, sure. But it uses lots of global variables, of course
IMO, if is not documented, it is a really strong contra argument for using MasmBasic (?)
Quote from: jj2007 on July 02, 2011, 05:45:29 AMhow do you use parallel threads?
mainly for data processing, but sometimes also for GUI threads...

Quote from: dedndave on July 02, 2011, 11:52:39 AM
not all data needs to be local
generally, it is only the variables that are written to that can cause trouble
the ideal 'thread save' program/library has only a const-section, no data section  :bg
FPU in a trice: SmplMath
It's that simple!

hutch--

It is a problem if the procedure needs to be re-entrant, you can use global scope variables in non critical operations if you don't mind tracking the globals but for re-entrant code you basically need a structure that holds all of the data you need and you pass its address to any dependencies that need that data. It is actiually a very efficient technique as you only need to pass the structure address so the stack overhead is very low and it is fast.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

jj2007

Quote from: qWord on July 02, 2011, 12:53:32 PM
Quote from: dedndave on July 02, 2011, 11:52:39 AM
not all data needs to be local
generally, it is only the variables that are written to that can cause trouble
the ideal 'thread save' program/library has only a const-section, no data section  :bg

Most of the global variables are read-only, like CrLf$ etc, but there are also many writeable ones, such as the structures that serve the Dim engine. However, even if you create A$(100) in thread A and B$(100) in thread B, they will never collide. There are some temporary general purpose buffers, such as for the deb macro, but even that should not cause trouble in any real life situations.

Of course, with a lot of acrobatic efforts, one could make a library with 100+ functions 'theoretically' thread-safe. But first, there are good reasons why I sometimes use global variables, and second, what for? If I really need a second thread, it's for performance reasons, so that is typically a highly optimised group of hand-crafted loops in which you would never use something as slow as a console print (not thread-safe) or string concatenation with Let - not thread-safe in theory, but in real life, you might find it very difficult to construct a conflict situation where two Let My$=Str$(eax) happen at exactly the same moment and draw on the common circular buffer used by Str$() and many other string functions.

So in short: If you are really scared about thread safety, 1. do not create threads, 2. if you have to, don't use MB functions in them, or 3., if you are paranoically scared, don't use MasmBasic for those proggies that require extra threads.

qWord

Quote from: jj2007 on July 02, 2011, 04:01:38 PM[...] but even that should not cause trouble in any real life situations.
in real life application it can and it does happen.
Quote from: jj2007 on July 02, 2011, 04:01:38 PMOf course, with a lot of acrobatic efforts, one could make a library with 100+ functions 'theoretically' thread-safe
it is very easy to create thread save: do not use globals. Sure, using Assmbler it is a bit more work than in c/c++,  but it is doable.

Quote from: jj2007 on July 02, 2011, 04:01:38 PMSo in short: If you are really scared about thread safety, 1. do not create threads, 2. if you have to, don't use MB functions in them, or 3., if you are paranoically scared, don't use MasmBasic for those proggies that require extra threads.
sry jj, I won't attack you!
However, some time back I've such problems while creating a DLL for Labview (for reading 1-wire temperature sensors) - my luck, I've discovert that bug while running a test some hours. It was cause by wrapper function for file I/O, that uses a static variable ...
FPU in a trice: SmplMath
It's that simple!

jj2007

Quote from: qWord on July 02, 2011, 04:45:01 PM
it is very easy to create thread save: do not use globals....
sry jj, I won't attack you!

Hi qWord,

I hope you understand my little dilemma:
- if I say MB is thread-safe, somebody will find an occasion to call me a liar;
- if I say it's not thread-safe, those noobs that could profit from having a simple HLL inside assembly will read it's not thread-safe...
The truth is that MasmBasic is not Basic, it's assembler - otherwise ml.exe or Jwasm.exe could not assemble a MB source. And although it's astonishingly fool-proof, an ambitious programmer will be able to produce a GPF. But you need to do really senseless things, such as
main thread:
Open "O", #1, "MyThreadA.txt"
2nd thread:
Open "I", #1, "MyThreadB.txt"
Believe me there will be problems (the handles table is global, and nope, I won't change that). But there won't be any problems if you "sensibly" use #2 in thread #2. Knowing all the inner structure of MB by heart, I might be able to construct some situations where a multi-threaded MB app crashes, but why stress myself intellectually if I can achieve the same "result" with a simple xor edx, edx - div edx? Long live assembler!

There is a big circular buffer that allows e.g. Print Str$(ebx), "=", Hex$(ebx), "=", Bin$(ebx), CrLf$ - but it could cause trouble if two threads decide to do a Print operation in exactly the same nanosecond. A mad programmer can achieve that on purpose, a sensible programmer or a noob would not be able to do such nonsense.

There are a handful of global vars shared between threads, such as file handles and array handles. They won't do any harm to each other but having them in global variables means that you can indeed read in a string array in thread A and use it in thread B. This is by design.
:bg