Adding Blocks to Inactive Dispatch Queue - objective-c

I have a situation where it would be helpful to be able to add blocks to an inactive queue which is then activated after another event happens. However, the entire thread from which I call dispatch_sync gets locked if the dispatch queue is suspended/inactive.
Is something like this possible? If not what other options do I have?
An example (not my actual use case):
#include <stdio.h>
#import <dispatch/dispatch.h>
int main(int argc, const char * argv[]) {
dispatch_queue_t my_queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_SERIAL_INACTIVE);
void (^b)(int) = ^void(int c) {
printf("%i\n", c);
};
for(int i = 1; i <= 1000; i++) {
dispatch_sync(my_queue, ^{ b(i); });
}
dispatch_activate(my_queue);
return 0;
}

I figured it out. Using dispatch_async fixed the problem.
Working solution:
#include <stdio.h>
#import <dispatch/dispatch.h>
int main(int argc, const char * argv[]) {
dispatch_queue_t my_queue = dispatch_queue_create("my_queue", DISPATCH_QUEUE_SERIAL_INACTIVE);
void (^b)(int) = ^void(int c) {
printf("%i\n", c);
};
for(int i = 1; i <= 1000; i++) {
dispatch_async(my_queue, ^{ b(i); });
}
dispatch_activate(my_queue);
return 0;
}

Related

Why Does This Objective C/C++ Code Require main.m instead of main.mm?

I get strange code errors when I rename the following command line program from main.m to main.mm. Works just fine as main.m. Anyone know why?
https://stackoverflow.com/a/36469891/105539
SOURCE
#import <Foundation/Foundation.h>
void detectNewFile (
ConstFSEventStreamRef streamRef,
void *clientCallBackInfo,
size_t numEvents,
void *eventPaths,
const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
int i;
char **paths = eventPaths;
printf("GOT AN EVENT!!!!\n");
for (i=0; i<numEvents; i++) {
printf("Change %llu in %s, flags %u\n", eventIds[i], paths[i], (unsigned int)eventFlags[i]);
}
}
int main(int argc, const char * argv[]) {
#autoreleasepool {
short nPathCount = 2;
CFStringRef mypath[nPathCount];
mypath[0] = CFSTR("/Users/mike/Documents");
mypath[1] = CFSTR("/Users/mike/Downloads");
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, nPathCount, NULL);
void *callbackInfo = NULL;
CFAbsoluteTime latency = 1.0; // seconds
FSEventStreamRef hStream = FSEventStreamCreate(NULL,
&detectNewFile,
callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
kFSEventStreamCreateFlagFileEvents
);
FSEventStreamScheduleWithRunLoop(hStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
FSEventStreamStart(hStream);
printf("Waiting on new file creations...\n");
CFRunLoopRun(); // runs in an endless loop, only letting the callback function run
} // end autorelease pool
return 0;
}
ERRORS
FOR:
char **paths = eventPaths;
Cannot initialize a variable of type 'char **' with an lvalue of type 'void *'
FOR:
FSEventStreamRef hStream = FSEventStreamCreate(NULL,
&detectNewFile,
callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow,
latency,
kFSEventStreamCreateFlagFileEvents
);
No matching function for call to 'FSEventStreamCreate'
Thanks to #johnelemans, I found the problems. In C, it's legal to have automatic casting from void * to char **, but not in C++, which is what the .mm file would switch this into. The fix is to use casting:
char **paths = (char **)eventPaths;
Then, on the FSEventStreamCreate, it didn't like the void * instead of this:
FSEventStreamContext *callbackInfo = NULL;
...and didn't like the CFAbsoluteTime instead of:
CFTimeInterval latency = 1.0; // seconds
Then, you need to add CoreServices.framework library to the build steps.
I made those changes and it compiles now.

functions calling from main method objective c

Here I need to write a function which is called from main method with integer array as a parameter please give me example.
In below example parameter are int type.
Note : please tell this is correct way to do this or not...
#import <Foundation/Foundation.h>
void displayit (int);
int main (int argc, const char * argv[])
{
#autoreleasepool {
int i;
for (i=0; i<5; i++)
{
displayit( i );
}
}
return 0;
}
void displayit (int i)
{
int y = 0;
y += i;
NSLog (#"y + i = %i", y);
}
Thanks in advance....
I tried out these, please check.
#import <Foundation/Foundation.h>
void displayit (int array[], int len);
int main (int argc, const char * argv[])
{
#autoreleasepool {
int array[]={1,2,3};
displayit( array, 3 );
}
return 0;
}
void displayit (int array[], int len)
{
for(int i=0;i<len;i++){
NSLog(#"display %d : %d",i,array[i]);
}
}
The out put is:
2014-10-30 14:09:32.017 OSTEST[32541:77397] display 0 : 1
2014-10-30 14:09:32.018 OSTEST[32541:77397] display 1 : 2
2014-10-30 14:09:32.018 OSTEST[32541:77397] display 2 : 3
Program ended with exit code: 0
I used another parameter len to avoid boundary beyond.
If the array is a global, static, or automatic variable (int array[10];), then sizeof(array)/sizeof(array[0]) works. Quoted From Another Question

Implementing a header in Objective C

I'm completely new to Objective C and I'm trying to use it to wrap a C-library. I have a main.m wrap.m and wrap.h files. From what I gather in the header file I included #interface and in the source file I will include #implementation However I'm not really understanding what to include in each of them. Right now my main file is:
int copy_data(struct archive *ar, struct archive *aw) {
for (;;) {
const void *buff;
size_t size;
off_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
archive_write_data_block(aw, buff, size, offset);
}
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_compression_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
r = archive_read_open_filename(a, argv[1], 10240);
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
r = archive_write_header(ext, entry);
if (archive_entry_size(entry) > 0) {
copy_data(a, ext);
}
archive_write_finish_entry(ext);
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
NSLog(#"No Issues");
}
return 0;
}
So far what I'm getting in my wrap.h file is:
typedef struct{
int *a;
int *ext;
}archive;
#interface main : NSObject
#property int flags;
#property int r;
I don't know if that is close to what I need to do, and I'm getting errors on my ARCHIVE_EXTRACT saying they are undeclared identifiers which I assume also have to go into my wrap.h file but I'm not sure how to do that. Any help at all would be appreciated!
If you start your project in Xcode using the CommandLineTool template, you can select your language to be "C" or "C++", so you wouldn't have to mess with Objective-C at all.
As for the .h file that you currently have, don't do "#property" or "#interface" for "main". "main" is a C style function and not an Objective-C thing.
If you are actually interested in an objectivec solution, follow Michael Dautermann's instructions to start a new Command Line project but instead of Type C use the Foundation option. This will give you a working main (just a regular c function). Then select new->objective c class to create your wrap.h/wrap.m. In the wrap.h you will pretty much exclusively be declaring your own objectivec public wrapper methods. In the wrap.m, you'll be importing what you want to wrap, and defining your wrapper functions.
//
// main.m
//
#import <Foundation/Foundation.h>
#import "wrap.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
[wrap wrappedStuff];
}
return 0;
}
//
// wrap.h
//
----------
#import <Foundation/Foundation.h>
#interface wrap : NSObject
+ (void)wrappedStuff;
#end
//
// wrap.m
//
#import "wrap.h"
#include "WhatImWrapping.h"
#implementation wrap
int copy_data(struct archive *ar, struct archive *aw) {
for (;;) {
const void *buff;
size_t size;
off_t offset;
int r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
archive_write_data_block(aw, buff, size, offset);
}
}
+ (void)wrappedStuff
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_compression_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
r = archive_read_open_filename(a, argv[1], 10240);
for (;;) {
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
r = archive_write_header(ext, entry);
if (archive_entry_size(entry) > 0) {
copy_data(a, ext);
}
archive_write_finish_entry(ext);
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
NSLog(#"No Issues");
}
#end

CGDisplayRegisterReconfigurationCallback: callback not called

Why doesn't the function displayChanged get fired in the following code?
#import <Cocoa/Cocoa.h>
static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) {
NSLog(#"%#, %#", displayID, flags);
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);
CFRunLoopRun();
}
return 0;
}
I'm physically removing (and plugging in) my external display, but the function is never run.
Why?
Just found the solution on this other question
Before calling CFRunLoopRun you have to call NSApplicationLoad to establish a connection with the window server. This is the fixed code for the original question:
#import <Cocoa/Cocoa.h>
static void displayChanged(CGDirectDisplayID displayID, CGDisplayChangeSummaryFlags flags, void *userInfo) {
NSLog(#"%u, %u", displayID, flags);
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
CGDisplayRegisterReconfigurationCallback(displayChanged, NULL);
NSApplicationLoad(); // establish a connection to the window server. In <Cocoa/Cocoa.h>
CFRunLoopRun(); // run the event loop
}
return 0;
}
I couldn't get CGDisplayRegisterReconfigurationCallback to work, so I used distributed notifications instead:
int main(int argc, const char * argv[]) {
#autoreleasepool {
[[NSDistributedNotificationCenter defaultCenter] addObserverForName:#"com.apple.BezelServices.BMDisplayHWReconfiguredEvent" object:nil queue:nil usingBlock:^(NSNotification *notification) {
NSLog(#"Displays changed!");
}];
CFRunLoopRun();
}
return 0;
}
If you're using AppKit (and have a running NSApplication event loop), you can listen for the NSApplicationDidChangeScreenParametersNotification notification. Or, you can implement the -applicationDidChangeScreenParameters: method in your application delegate, which amounts to the same thing.

Nested functions are disabled; use f-nested functions to re-enable

I am just learning Objective C and I am having great difficulty. This is what is typed and it is giving me an error. I typed the text that is bold. What is wrong with it. It gives me the nested function error right after int main(void)
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [NSAutoreleasePool alloc] init];
// **#include <stdio.h>
int main(void)
int amount = 1000000;
printf("The amount in your account is $%i\n", amount);
return 0;
}**
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
Your problem is that C and it's brethren do not like functions within functions (putting aside gcc extensions for now).
What you seem to be trying to do is to declare a whole new main inside your main. That's a big no-no. What I suspect is that you've cut-and-pasted an entire C program into the middle of your existing main.
Start with:
#import <Foundation/Foundation.h>
#include <stdio.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [NSAutoreleasePool alloc] init];
int amount = 1000000;
printf("The amount in your account is $%i\n", amount);
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
and work your way up from there.