Proper disposal of a Grand Central Dispatch I/O channel - objective-c

I'm confused about how to correctly dispose of a Grand Central Dispatch I/O channel once I'm finished with it. The following (simplified) example causes a crash on some private dispatch queue with the message: BUG IN CLIENT OF LIBDISPATCH: Over-resume of an object:
- (void)beginReading {
dispatch_io_t channel;
channel = dispatch_io_create_with_path(DISPATCH_IO_RANDOM,
"/Path/To/Some/File",
O_RDONLY,
0 /*mode*/,
someQueue,
^(int errorCode) {
// Cleanup handler; executed once channel is closed.
// (Or fails to open.)
});
// Schedule the read operation
dispatch_io_read(channel, 0, SIZE_MAX, someQueue, ^(bool done, dispatch_data_t data, int errorCode) {
NSError *error = (errorCode!=0) ? [NSError errorWithDomain:NSPOSIXErrorDomain code:errorCode userInfo:nil] : nil;
[self didReadChunk:data isEOF:done error:error];
});
// No more read operations to come, so we can safely close the channel.
// (Or can we?)
dispatch_io_close(channel, 0);
// We don't need a reference to the channel anymore
dispatch_release(channel);
}
I'm guessing that dispatch_io_close() schedules some asynchronous operation to close the channel, and until this operation has finished executing, you mustn't call dispatch_release()on the channel or bad things will happen. But this would be quite surprising: other GCD asynchronous functions, such as dispatch_async(), don't have this restriction. Further, the dispatch_io_close() call doesn't seem to be strictly necessary, as libdispatch appears to close the file with the last call to dispatch_release() on the channel.
It seems to follow from this that if you call dispatch_io_close, you must take care that not to release the channel until its cleanup handler has run. This so irritating that I wonder if it's a bug. Or perhaps I'm missing something?

It turns out this is a bug (radar #10246694). Further experimenting seems to indicate that it only affects path-based dispatch channels, i.e. those created with dispatch_io_create_with_path(), as opposed to dispatch_io_create().

Declare these variables, globally:
dispatch_fd_t write_dfd, read_dfd;
dispatch_io_t write_channel, read_channel;
To open a channel for writing a Metal texture to a file:
NSString *documentDictionary = [(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)) objectAtIndex:0];
    
        write_dfd = open([[NSString stringWithFormat:#"%#/textures.data", documentDictionary] UTF8String], O_CREAT | O_TRUNC | O_WRONLY | O_APPEND);
        write_channel = dispatch_io_create(DISPATCH_IO_STREAM, write_dfd, AppServices.textureQueue, ^(int error) {
            NSLog(#"Write channel to %# open", documentDictionary);
        });
        
        dispatch_io_set_low_water(write_channel, 33177608);
        dispatch_io_set_high_water(write_channel, 33177608);
To write a Metal texture to a file:
void *write_buffer = malloc([_textureBGRA allocatedSize]);
    [_textureBGRA getBytes:write_buffer bytesPerRow:15360 fromRegion:MTLRegionMake2D(0.0, 0.0, [_textureBGRA width], [_textureBGRA height]) mipmapLevel:0];
    dispatch_data_t message_data = dispatch_data_create(write_buffer, [_textureBGRA allocatedSize], AppServices.textureQueue, ^{
        free((void *)write_buffer);
    });
    dispatch_io_write(write_channel, 0, message_data, AppServices.textureQueue, ^(bool done, dispatch_data_t  _Nullable data, int error) {
        if (done)
        {
            NSLog(#"Wrote %lu bytes",  [_textureBGRA allocatedSize]);
        }
    });
To close the file:
dispatch_io_close(write_channel, 0);
close(write_dfd);
To open a channel for reading a Metal texture from a file:
NSString *documentDictionary = [(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)) objectAtIndex:0];
        
        read_dfd = open([[NSString stringWithFormat:#"%#/textures.data", documentDictionary] UTF8String], O_RDONLY | O_NONBLOCK);
        read_channel = dispatch_io_create(DISPATCH_IO_STREAM, read_dfd, dispatch_get_main_queue(), ^(int error) {
            NSLog(#"Read channel to %# open", documentDictionary);
        });
        
        dispatch_io_set_low_water(read_channel, 33177608);
        dispatch_io_set_high_water(read_channel, 33177608);
To read a Metal texture from a file:
dispatch_io_read(read_channel, [_textureBGRA allocatedSize] * textureIndex, [_textureBGRA allocatedSize], dispatch_get_main_queue(), ^(bool done, dispatch_data_t  _Nullable data, int error) {
                if ( read_channel == nil )
                    return;
                
                if ( error != 0 ) {
                    __autoreleasing NSError * nsError = nil;
                    nsError = [[NSError alloc] initWithDomain:NSPOSIXErrorDomain code:error userInfo:nil];
                    NSLog(#"Error reading from channel: %#", nsError.localizedDescription);
                    return;
                }
                
                // read data
                void *buffer = malloc([_textureBGRA allocatedSize]);
                dispatch_data_t mapped_data = dispatch_data_create_map(data, buffer, NULL);
                dispatch_data_apply(mapped_data, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
                    NSUInteger rowBytes = 3840 * 4;
                    NSUInteger imageBytes = rowBytes * 2160;
                    MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
                                                                                                                 width:3840
                                                                                                                height:2160
                                                                                                             mipmapped:NO];
                    textureDescriptor.usage = MTLTextureUsageShaderRead;
                    id<MTLTexture> texture = [_device newTextureWithDescriptor:textureDescriptor];
                    [texture replaceRegion:MTLRegionMake2D(0, 0, 3840, 2160)
                               mipmapLevel:0 slice:0 withBytes:buffer
                               bytesPerRow:rowBytes bytesPerImage:imageBytes];
                    dispatch_async(dispatch_get_main_queue(), ^{
                        NSString *label = [NSString stringWithFormat:#"%lu", textureIndex];
                        const char *queue_index = [[NSString stringWithFormat:#"%lu", textureIndex] cStringUsingEncoding:NSUTF8StringEncoding];
                        dispatch_queue_set_specific(AppServices.textureQueue, queue_index, (void *)CFBridgingRetain(texture), NULL);
                        [self.mediaCollectionView insertItemForQueueDataIndex:label];
                        textureIndex++;
                    });
                    return TRUE;
                });
            });
To close the file:
dispatch_io_close(read_channel, 0);
close(read_dfd);

Related

item in flatlist does not refresh

I want to change tintcolor of a picture when pressing on touchanbleopacity
I wrote this code, but when i press, tintcolor changes in array, but not in flatlist.
…;
let posts = [some_data]
const SomeScreen = ({navigation}) => {
    …
    function setColor(item){
        if (posts[item.id].color == 'red'){
            posts[item.id].color = '#8B8D8E'
            posts[item.id].bgColor = '#232323'
        }
        else{
            posts[item.id].color = 'red'
            posts[item.id].bgColor = '#3E2526'
        }
    }
   
    return(
   …
            <FlatList
                data={posts}
                keyExtractor={item=>item.id}
                extraData={posts}
                refreshControl={
                    <RefreshControl
                      refreshing={refreshing}
                      onRefresh={onRefresh}
                    />
                  }
                renderItem={({item}) =>{
                    …
<TouchableOpacity onPress={() => {setColor(item)}}>
<View style={…}>
<Image source={…} style={{…, tintColor: item.likeColor}}/>
    </View>
</TouchableOpacity>
</View>
</FlatList>
…
);
}
…
I tried to use extraData, but nothing happened.
How can i fix it?

Mimicing the same logic as my sql statement not working with cfscript/cfml?

I am coming to a problem where I am moving from sql query to use of an api. So, I started doing the same thing that my sql statement is doing. But for some reason it is retrieving all the job status and job class and pay grades. However, what my expected results should be is where when I delete a job_class which is something like 0707 from the json or from the database it will show on my screen that that job class is missing if no job class is missing then it will just show a Struct (empty). Can anyone tell me what I am doing wrong in my code? thanks for the help.
SQL:
select distinct job_class, PAY_GRADE
from app.my_databaseFone
where job_status like 'Active'
order by job_class
Code:
<cffunction  name="my_api"
    access="private"
    description="my api data">
   
     <cfset qFullmyApi = fileRead("C:\Users\Desktop\myjson.json")>  
     <cfset jsonData = deserializeJSON(qFullmyApi) />  
     
      <cfscript>
     
     
        myAPIOutput = {};
     
     
   
      for (item in jsonData) {
 
       
        if (structKeyExists(myAPIOutput, item.jobStatus)) {
           
              matchedValue = false;
                 for (i=1; i <= arrayLen(myAPIOutput[item.jobStatus]); i=i+1) {
                         
                   if (item.jobClass == myAPIOutput[item.jobStatus][i].job_class
                    && item.payGrade == myAPIOutput[item.jobStatus][i].pay_grade) {
   
                         matchedValue = true;
                            break;
                   
   
                   }
     
              }
               if (matchedValue == false) {
   
                   arrayAppend(myAPIOutput[item.jobStatus], {"JOB_CLASS":item.jobClass,
                   "PAY_GRADE": item.payGrade});
   
               }
            } else {
               
                myAPIOutput[item.jobStatus] = [{"JOB_CLASS":item.jobClass,
                 "PAY_GRADE": item.payGrade}];
           }
   
        }
           
        return myAPIOutput;
   
         
   
      </cfscript>
</cffunction>
In your WHERE clause, you filter for job_status like 'Active' (btw, no need for like here, use = instead) but there is NO similar filter in your ColdFusion code.
myAPIOutput will include all job_status types not just Active ones. Just display the ones in myAPIOutput['Active'] and that should match to your SQL query. If there is no active jobs at all, myAPIOutput['Active'] not exists

Excessive memory footprint when storing JSON (as NSData) on Core Data Object via ARC in Core Data

     
I am loading several hundred MB filesets into Core Data.  Instead of using relational joins, I've discovered that I get much better perfomance by creating NSDictionaries / NSArray's, and serializing them onto the Core Data records.   The problem thus far is taht my memory footprint goes through the roof due ot malloc's attributed to this line:  
NSMutableDictionary *stackEntryDictionary = [NSMutableDictionary dictionary];
NSDictionary *stackDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                [NSString stringWithUTF8String:parts[6].c_str()], #"relationship"
                                , [NSString stringWithUTF8String:parts[8].c_str()], #"sequenceId"
                                , [NSString stringWithUTF8String:parts[9].c_str()], #"sequence"
                                , [NSString stringWithUTF8String:parts[7].c_str()], #"block"
                                , [NSNumber numberWithInteger:row], #"entryId"
                                , nil ];
if ([relationship isEqualToString:#"consensus"] || [relationship isEqualToString:#"model"]) {
                            [stackEntryDictionary setObject:stackDictionary forKey:relationship];
                            row = 1;
                        }
                        else {
                            [stackEntryDictionary setObject:stackDictionary forKey:[NSNumber numberWithInt:row].stringValue];
                            ++row;
                        }
stackEntryDatumMO = [NSEntityDescription insertNewObjectForEntityForName:#"StackEntryDatum" inManagedObjectContext:document.managedObjectContext];
stackEntryDatumMO.sampleId = sampleMO.sampleId;
stackEntryDatumMO.name = sampleMO.name;
stackEntryDatumMO.tagId = [NSNumber numberWithInteger:locusId];
// THIS IS THE "BAD LINE" that issues a lot of NSString malloc's 
stackEntryDatumMO.stackData = [NSJSONSerialization dataWithJSONObject:stackEntryDictionary options:0 error:&error];
 
This gets cleaned up when I am fully out of the loop (about 70K of these per file, for 30 files, and the average size of the insert dictionary is roughly 20).   However, I'm sporting about 10 GB's of memory which kills application performance and is unnecessary.  
So, I have two questions:
1 - How would you suggest that I embed objects onto Core Data (or do you suggest)? 
2 - Is there a better JSON serialization library that would offer a lower memory footprint? 
3 - Should I abandon ARC and if so how?
4 - Any other suggestions?   Using a separate import "Application" would be a possible alternate interim solution, but not something that I'd be willing to see posted on the App-Store long-term.  
I should also mention that when ARC cleans up after the load, it will kill the application as it tries to release objects that have already been released (can post error later if need be).   This does not happen on smaller files.  
Try wrapping the NSJSONSerialization call in an #autoreleasepool, it creates a ton of autoreleased objects that aren't needed after the call.
As for what you're doing, storing them as NSData will incur the same memory footprint in CoreData as storing them in their own file. You'll pay a bit more per object for the stuff required by NSManagedObject but the net cost is approximately the same.
You can tune the footprint by forcing the CoreData objects to deallocate more frequently, the most abrupt way to do this is to save and then deallocate the managed object context you are using. Apply #autoreleasepool as necessary.
It would also help if you can post a sample of the Instruments allocations instrument while in the loop, or a snapshot of the heap.

How can I change the event marks on TapkuLibrary calendar object

I use TapkuLibrary for my calendar. I want to change the event marks, for example to show different operations on certain days of the month. I want to achieve something like the second image.
Default TapkuLibrary calendar
I want to like something like this
N.B. I'm first going to explain how Tapku currently draws its MonthView marks, and then I'll propose a way to change it.
Tapku doesn't actually set those marks as images; it sets them as strings! Search TKCalendarMonthView for •. The marks are set in two different places in TKCalendarMonthView: First, in the drawTileInRect:day:mark:font... method, which is called on each tile individually in the drawRect method. Second, with the property 'dot', which is applied to the user's 'selected' cell, which has a different text color, etc. and thus needs to have its own properties adjusted.
To set your own images, you'll have to modify Tapku in those two places (not terribly difficult; it's a pretty accessible project). So, instead of setting the cell's text to •, you'll have to set its image to an image you provide.
Providing this image could be done in a few different ways. The most straightforward will be to redo Tapku's concept of the 'marks' array (set by the delegate). Instead of creating an array of integers, perhaps you could create an array of UIImages. Still, you need to have a way to tell the code "no image"--maybe have a blank image and just apply it to cells by default?
Let me know if you need any clarification.
use bellow method instead of - DrawTileInRect
for multiple color in one month , check date
- (void) drawTileInRect:(CGRect)r day:(int)day mark:(BOOL)mark font:(UIFont*)f1 font2:(UIFont*)f2 sysFlag:(int)sysFlg userEventFlg:(int)userEventFlag diaryFlg:(int)diaryFlag momentsFlg:(int)momentsFlag
{
   
    #try {
        
        NSString *str = [NSString stringWithFormat:#"%d",day];
        [str retain];
        
        
        r.size.height -= 2;
        [str drawInRect: r
               withFont: f1
          lineBreakMode: UILineBreakModeWordWrap
              alignment: UITextAlignmentCenter];
        
        r.size.height = 10;
        r.origin.y += 18;
        
        CGRect y=CGRectMake(r.origin.x+5, r.origin.y-25, 12, 12);//5 5
        
        
        CGRect rect1=CGRectMake(r.origin.x, r.origin.y+7, 12, 12);
        CGRect rect2=CGRectMake(rect1.origin.x+18, r.origin.y+7, 12, 12);
        CGRect rect3=CGRectMake(rect2.origin.x+16, r.origin.y+7, 12, 12);
        
        if(sysFlg==1)
        {
            [[UIImage imageNamed:#"Blue_dot.png"] drawInRect:y];
        }
        
        if(userEventFlag==1)//1.png
        {
            [[UIImage imageNamed:#"Yellow_dot.png"] drawInRect:rect1];
        }
       
        
        if(momentsFlag==1)//3.png
        {
            [[UIImage imageNamed:#"Red_dot.png"] drawInRect:rect3];
        }
        
    }
    #catch (NSException * e) {
        NSLog(#"Exception: %#", e);
    }
}

Safari is crashing when JVM get killed

i was crawling google couple of hours to search for that kind of problem but i could not find any working solution, i hope your guys can help me out!
i have a java applet which read the COM ports, after that process i gonna kill it to be able to read it again with another applet which gets loaded after i redirect the user to another page.
The problem is when i kill the first applet, the hole browser crashes or is closing for no reason...
below my killer function ^^
public void killMobileChecker() {
       try {
           System.exit(0);
       } catch (Exception ex) {
           if (log_level >= 4) {
               ex.printStackTrace();
           }
       }
   }
if i dont call that function safari will not close/crash but the next java applet is not able anymore to read the COM port.
Does anybody have a clue what safari or likely me is doing wrong?
** Edit
script to kill all open threads
private void closeConnection() {
       if (portId != null && port_opened) {
           try {
               if (input != null) {
                   input.close();
               }
               if (output != null) {
                   output.close();
               }
               if (serialPort != null) {
                   serialPort.close();
               }
               port_opened = false;
           } catch (Exception ioe) {
               if (log_level >= 4) {
                   ioe.printStackTrace();
                   System.out.println("System_Error_closing_Comm_Port");
               }
           }
           if (log_level >= 4) {
               System.out.println("\r\nMobile Comm port closed\r\n");
           }
//                LogUtilities.writeLog("\r\nClosing Mobile Comm port...\r\n");
       }
   }
Which JVM version are you using? After jdk1.6 update 10 the applet should utilize a separate process from the browser. Before that time browser and applet shared the same process.