Why not foos[1].bar instead of the 'convert / unsafe_load' code? While my data really isn't immutable, this might be ok if there is a relatively cheap way to create a copy of an immutable object while changing one or two values. For example,
immutable Foo x::Int y::Float64 Foo(old::Foo; x = old.x, y = old.y) = new(x,y) end map[1] = Foo(map[1], x = 1) But this seems expensive, particularly with many more than two fields (I'm thinking between 8 and 20). And it seems to be getting back to ugly, since it isn't much different than setfield(foo, :x, 1). Plus, unlike with setfield, I don't see a way of passing x=1 programmatically, like by passing a tuple or something containing (:x,1) to Foo's constructor. Can I safely use pointer conversion to overwrite the data inside an immutable object, thereby making it mutable? I would think not; it seems dangerous. Is there any documentation on the internal functions like unsafe_load in your example? Or even just a list of them? I don't mind playing under the covers, even if that means my code breaks between versions of Julia. > On Mar 25, 2014, at 4:44 PM, Jameson Nash <[email protected]> wrote: > > Or you could make a do block, to create a scope for an explicit finalization > step > >> On Tuesday, March 25, 2014, Stefan Karpinski <[email protected]> wrote: >> If you use an immutable type and replace whole records, then you can mmap it: >> >> julia> immutable Foo >> bar::Int >> baz::Float64 >> end >> >> julia> foos = Array(Foo,10) >> 10-element Array{Foo,1}: >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> Foo(0,0.0) >> >> julia> foos[1] = Foo(1,2) >> Foo(1,2.0) >> >> julia> p = convert(Ptr{Int},pointer(foos)) >> Ptr{Int64} @0x00007ff36d436af0 >> >> julia> unsafe_load(p,1) >> 1 >> >> julia> unsafe_load(p,2) >> 4611686018427387904 >> >> julia> reinterpret(Float64,unsafe_load(p,2)) >> 2.0 >> >> Not as convenient as mutating these in place, but maybe ok. >> >> >>> On Tue, Mar 25, 2014 at 5:35 PM, Keith Mason <[email protected]> wrote: >>> This is a database application, with a large number of rows per table. So >>> probably not, for two reasons. >>> >>> One, in the event the application crashes, I would like the data to be >>> updated to disk on a per transaction basis. I can deal with the problem of >>> when to call flush() separately. >>> >>> Two, I would still need to keep track of which data had been updated, so I >>> only have to write the data that had been changed. Same problem applies. >>> >>> Keith >>> >>>> On Mar 25, 2014, at 4:14 PM, Jameson Nash <[email protected]> wrote: >>>> >>>> Could you do all of the work in a finalizer ? >>>> >>>>> On Tuesday, March 25, 2014, Keith Mason <[email protected]> wrote: >>>>> I definitely understand that. I would honestly prefer to be able to >>>>> memory map directly to the disk file and let the OS do the writes behind >>>>> the scenes. Less potential for performance penalties that way. But I >>>>> haven't found a way in Julia to do that. mmap_array obviously only takes >>>>> arrays and not singular objects. I could, of course, mmap_array a type >>>>> into an array of length 1. But the real problem is that composite types >>>>> are handled as pointers, so mmap_array on a composite type results in the >>>>> pointers being written to disk and not the actual data. Obvious problems >>>>> abound with that. >>>>> >>>>> I have had success in using mmap_array on immutable types, but the >>>>> problem with that is that they are immutable. I need to be able to >>>>> modify individual fields. >>>>> >>>>> In C, I can declare a struct, and then cast the pointer of the mmap >>>>> function to the struct pointer. That doesn't seem to be an option in >>>>> Julia. >>>>> >>>>> If there is another solution I haven't thought of yet, I'm all ears! >>>>> >>>>>> On Tuesday, March 25, 2014 4:02:09 PM UTC-5, Patrick O'Leary wrote: >>>>>>> On Tuesday, March 25, 2014 3:48:22 PM UTC-5, Keith Mason wrote: >>>>>>> I have a number of variables based on composite types. I want the >>>>>>> fields of these variables synced to disk, so that every time I modify a >>>>>>> field, the data is written to disk. Is there any way to do this with >>>>>>> assignment notation? >>>>>> >>>>>> As a more general note, hiding something as expensive as disk access >>>>>> behind an overloaded `setfield!()` may make performance characteristics >>>>>> less intuitive, and make tuning that performance--say, by batching >>>>>> operations together--more difficult. Something to think about.
