Thank you for your response Jim.
I wanted to follow up with what I determined to be my best possible solution to this problem. The real problem was that I needed to know the dimensions of the structure in order to map the structure to shared memory for child processes using IDL to IDL bridges. This means that for Shmmap to run in the child process I would need access to the structure in that process in order to use it as a template, negating the purpose. What I did to solve this issue is to create an [3,n] matrix to store the dimensions of all the sub-matrices within my structure.
;Test Structure is x.(n).(n) for subset array
y={one0:fltarr(5,3,2), one1:fltarr(5,1,1), one2:fltarr(5,3,8), one3:fltarr(5,3,2)}
z={two0:fltarr(2,3,1895), two1:fltarr(2,3,1), two2:fltarr(2,3,5)}
m={three0:fltarr(3,3,20), three1:fltarr(3,3,1), three2:fltarr(3,3,2)}
x=create_struct('t1',y, 't2',z, 't3',m)
I created a function which pulled apart the dimensions of my structure (I know the general layout of my structure, so this code would need to be modified to be more inclusive of different structure layouts).
;Create template for sharing structures in memory across multiple threads
function templ_str, in_array
COMPILE_OPT IDL2
;build and return a template
strt = list()
print, n_tags(in_array)
for i=0, n_tags(in_array)-1 do begin
for r=0, n_tags(in_array.(i))-1 do begin
tmp_dim = size(in_array.(i).(r), /dim)
case_test = n_elements(tmp_dim)
CASE case_test OF
3: strt.add, [size(in_array.(i).(r),/dim)]
2: strt.add, [(size(in_array.(i).(r),/dim)),1]
1: strt.add, [(size(in_array.(i).(r),/dim)),1,1]
ENDCASE
endfor
endfor
strt = strt.ToArray(/transpose, type='ULONG') ; Array which describes structure level and dimensions
return, strt
end
I shared the resulting array describing the template of the structure in shared memory and sent to child processes via my standard method. Then I ran a Threads->execute in the child process to build the template back into a properly sized structure for use as a template
for i = 0 , n_elements(oThreads )-1 do oThreads[i]->Execute, "void = build_str(threaderror=threaderror)"
function build_str, threaderror=threaderror
COMPILE_OPT IDL2
threaderror = 0
; catch error block
catch, errno
if (errno ne 0) then begin
catch, /cancel
help, /last_message, output=errText
threaderror = errText
return, threaderror
endif
;Reconstruct base structure for template
StructDATA = SHMVAR('StructMEM') ; structure template array
n_lvls = StructDATA[0,uniq(StructDATA[0,*])]
templ_str = {} ; !NULL holding variable for concatenation
foreach lvl, n_lvls do begin
sub_str = {} ; !NULL holding variable to make arrays in
this_lvl = StructDATA[*,where(StructDATA[0,*] EQ lvl)]
for i=0, n_elements(this_lvl[0,*])-1 do begin
mArr = this_lvl[*,i]
sub_str = create_struct(sub_str, 'xEMn'+strtrim(i,2), fltarr(mArr[0],mArr[1],mArr[2]))
endfor
templ_str = create_struct(templ_str, 'xEM'+strtrim(lvl,2),sub_str)
endforeach
;Place template for structure in each child process
SHMMAP, 'MainSTRUCT', TEMPLATE=templ_str
templ_str = 0
return, 1
end
From there I could use SHMVAR to pull in the structure where it was needed for other functions in the child process.
Side note: I use this for error checking,
for i = 0 , n_elements( oThreads )-1 do begin
error_ret = oThreads[i]->Getvar('threaderror')
if error_ret[0] then begin
print, error_ret
void = dialog_message(error_ret, /error)
stop
endif
endfor
Having said that, additional research turned up Slug's guide to IDL (
http://slugidl.pbworks.co...9/Child%20Processes) that has a program, struct_pass.pro which is supposed to send a structure to a child process which may be able to achieve template sending more easily. I didn't test it however.
Thanks for the help!