Skip to content

Instantly share code, notes, and snippets.

Avatar

Justin Spahr-Summers jspahrsummers

View GitHub Profile
@jspahrsummers
jspahrsummers / gist:4305792
Last active Apr 29, 2021
CGRectDivideWithPadding illustrations
View gist:4305792

Simple visual illustrations of how CGRectDivideWithPadding works.

Slicing from CGRectMinXEdge
  +-------+---------+------------>
e |       |         |
d | slice | padding | remainder…
g |       |         |
e |       |         |
@jspahrsummers
jspahrsummers / bad.m
Last active Jan 20, 2021
Synchronizing with multiple GCD queues
View bad.m
//
// DON'T do this, or else you risk a deadlock (e.g., by accidentally performing it in a different order somewhere)
//
dispatch_async(firstQueue, ^{
dispatch_sync(secondQueue, ^{
// code requiring both queues
});
});
@jspahrsummers
jspahrsummers / GHRunLoopWatchdog.h
Created Jan 28, 2015
A class for logging excessive blocking on the main thread
View GHRunLoopWatchdog.h
/// Observes a run loop to detect any stalling or blocking that occurs.
///
/// This class is thread-safe.
@interface GHRunLoopWatchdog : NSObject
/// Initializes the receiver to watch the specified run loop, using a default
/// stalling threshold.
- (id)initWithRunLoop:(CFRunLoopRef)runLoop;
/// Initializes the receiver to detect when the specified run loop blocks for
@jspahrsummers
jspahrsummers / AsynchronousGenerators.md
Last active Jan 4, 2020
Python asynchronous generator semantics and types
View AsynchronousGenerators.md

How to use asynchronous generators

The documentation 6.2.9.4. "Asynchronous generator-iterator methods" is phrased really ambiguously. To make matters worse, typing.AsyncGenerator is not specified fully correctly.

Here, I attempt to more clearly capture the actual interface contract, based on what I've read and observed. See also PEP 492 -- Coroutines with async and await syntax and PEP 525 -- Asynchronous Generators.

This might be useful to implement lower-level behaviors than you can with async for, like sending values into the generator function.

TSend = TypeVar('TSend', contravariant=True)
@jspahrsummers
jspahrsummers / gist:5780224
Last active Sep 26, 2019
Untested proof of concept for a better @weakify macro.
View gist:5780224
#define $(...) \
({ \
__weak __typeof__(self) weakSelf = self; \
\
^(__VA_ARGS__) { \
__strong __typeof__(weakSelf) self = weakSelf; \
$_body_
#define $_body_(...) \
__VA_ARGS__ \
@jspahrsummers
jspahrsummers / gist:7080228
Last active May 2, 2019
Advantages and disadvantages to RACCommand under MVVM
View gist:7080228

MVVM example

For a command that initiates a network request when:

  • The network connection is up (precondition)
  • The network request is not already in progress (enforced serialization)

The lifecycle proceeds as follows:

  1. The view model exposes the command and describes its behavior
@jspahrsummers
jspahrsummers / main.m
Created Nov 24, 2015
[NSThread isMainThread] is probably not what you want!
View main.m
#import <Foundation/Foundation.h>
int main (int argc, const char **argv) {
@autoreleasepool {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"is main thread? %i", (int)[NSThread isMainThread]);
});
});
@jspahrsummers
jspahrsummers / gist:1670404
Created Jan 24, 2012
Macro for safer key-value coding
View gist:1670404
#define ObjectKeyPath(OBJECT, KEYPATH) \
((void)(NO && ((void)OBJECT.KEYPATH, NO)), @ # KEYPATH )
NSString *str = @"foobar";
NSLog(@"%@", [str valueForKey:ObjectKeyPath(str, length)]);
@jspahrsummers
jspahrsummers / GHReadWriteQueue.h
Last active Dec 22, 2016
Non-blocking mutual exclusion with readers and writers, for asynchronous operations that may span more than one GCD block (making a single concurrent GCD queue unsuitable).
View GHReadWriteQueue.h
//
// GHReadWriteQueue.h
// GitHub
//
// Created by Justin Spahr-Summers on 2014-03-24.
// Copyright (c) 2014 GitHub. All rights reserved.
//
#import <Foundation/Foundation.h>
@jspahrsummers
jspahrsummers / gist:986175
Created May 23, 2011
Tentative coroutine syntax
View gist:986175
#define coroutine(ARGS) \
__block unsigned long ext_coroutine_line_ = 0; \
\
return ^(ARGS){ \
for (;; ext_coroutine_line_ = 0) \
switch (ext_coroutine_line_) \
default:
#define return_coroutine \
}