Skip to content

Commit

Permalink
iOS - clean up weakproxy gating
Browse files Browse the repository at this point in the history
Summary: The proper weakproxy usage should be enabled by default from now on.

Reviewed By: PeteTheHeat

Differential Revision: D17866448

fbshipit-source-id: da404a41fd1136d7feebfc7591fa2965a65c4c6b
  • Loading branch information
fkgozali authored and facebook-github-bot committed Oct 11, 2019
1 parent 299eb9f commit abf612a
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 36 deletions.
2 changes: 0 additions & 2 deletions Libraries/Image/RCTUIImageViewAnimated.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#import <React/RCTAnimatedImage.h>
#import <React/RCTDefines.h>

RCT_EXTERN void RCTUIImageViewEnableWeakProxy(BOOL enabled);

@interface RCTUIImageViewAnimated : UIImageView

@end
57 changes: 23 additions & 34 deletions Libraries/Image/RCTUIImageViewAnimated.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@
#import <mach/mach.h>
#import <objc/runtime.h>

static BOOL weakProxyEnabled = YES;
void RCTUIImageViewEnableWeakProxy(BOOL enabled) {
weakProxyEnabled = enabled;
}

static NSUInteger RCTDeviceTotalMemory() {
return (NSUInteger)[[NSProcessInfo processInfo] physicalMemory];
}
Expand All @@ -26,7 +21,7 @@ static NSUInteger RCTDeviceFreeMemory() {
vm_size_t page_size;
vm_statistics_data_t vm_stat;
kern_return_t kern;

kern = host_page_size(host_port, &page_size);
if (kern != KERN_SUCCESS) return 0;
kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
Expand Down Expand Up @@ -61,7 +56,7 @@ - (instancetype)initWithFrame:(CGRect)frame
if (self = [super initWithFrame:frame]) {
self.lock = dispatch_semaphore_create(1);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];

}
return self;
}
Expand Down Expand Up @@ -91,28 +86,28 @@ - (void)setImage:(UIImage *)image
if (self.image == image) {
return;
}

[self stop];
[self resetAnimatedImage];

if ([image respondsToSelector:@selector(animatedImageFrameAtIndex:)]) {
NSUInteger animatedImageFrameCount = ((UIImage<RCTAnimatedImage> *)image).animatedImageFrameCount;

// In case frame count is 0, there is no reason to continue.
if (animatedImageFrameCount == 0) {
return;
}

self.animatedImage = (UIImage<RCTAnimatedImage> *)image;
self.totalFrameCount = animatedImageFrameCount;

// Get the current frame and loop count.
self.totalLoopCount = self.animatedImage.animatedImageLoopCount;

self.animatedImageScale = image.scale;

self.currentFrame = image;

dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
self.frameBuffer[@(self.currentFrameIndex)] = self.currentFrame;
dispatch_semaphore_signal(self.lock);
Expand All @@ -123,7 +118,7 @@ - (void)setImage:(UIImage *)image
if ([self paused]) {
[self start];
}

[self.layer setNeedsDisplay];
} else {
super.image = image;
Expand Down Expand Up @@ -151,20 +146,14 @@ - (NSOperationQueue *)fetchQueue

- (CADisplayLink *)displayLink
{
// TODO (T53783620): This logic should always be enabled.
if (weakProxyEnabled) {
// We only need a displayLink in the case of animated images, so short-circuit this code and don't create one for most of the use cases.
// Since this class is used for all RCTImageView's, this is especially important.
if (!_animatedImage) {
return nil;
}
// We only need a displayLink in the case of animated images, so short-circuit this code and don't create one for most of the use cases.
// Since this class is used for all RCTImageView's, this is especially important.
if (!_animatedImage) {
return nil;
}

if (!_displayLink) {
__weak typeof(self) weakSelf = self;
// TODO (T53783620): This logic should always be enabled.
id target = weakProxyEnabled ? [RCTWeakProxy weakProxyWithTarget:self] : weakSelf;
_displayLink = [CADisplayLink displayLinkWithTarget:target selector:@selector(displayDidRefresh:)];
_displayLink = [CADisplayLink displayLinkWithTarget:[RCTWeakProxy weakProxyWithTarget:self] selector:@selector(displayDidRefresh:)];
NSString *runLoopMode = [NSProcessInfo processInfo].activeProcessorCount > 1 ? NSRunLoopCommonModes : NSDefaultRunLoopMode;
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
}
Expand Down Expand Up @@ -199,7 +188,7 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
NSUInteger totalFrameCount = self.totalFrameCount;
NSUInteger currentFrameIndex = self.currentFrameIndex;
NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount;

// Check if we have the frame buffer firstly to improve performance
if (!self.bufferMiss) {
// Then check if timestamp is reached
Expand All @@ -216,7 +205,7 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
self.currentTime = nextDuration;
}
}

// Update the current frame
UIImage *currentFrame;
UIImage *fetchFrame;
Expand All @@ -243,7 +232,7 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
} else {
self.bufferMiss = YES;
}

// Update the loop count when last frame rendered
if (nextFrameIndex == 0 && !self.bufferMiss) {
// Update the loop count
Expand All @@ -255,7 +244,7 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
return;
}
}

// Check if we should prefetch next frame or current frame
NSUInteger fetchFrameIndex;
if (self.bufferMiss) {
Expand All @@ -265,7 +254,7 @@ - (void)displayDidRefresh:(CADisplayLink *)displayLink
// Or, most cases, the decode speed is faster than render speed, we fetch next frame
fetchFrameIndex = nextFrameIndex;
}

if (!fetchFrame && !bufferFull && self.fetchQueue.operationCount == 0) {
// Prefetch next frame in background queue
UIImage<RCTAnimatedImage> *animatedImage = self.animatedImage;
Expand Down Expand Up @@ -295,7 +284,7 @@ - (void)calculateMaxBufferCount
{
NSUInteger bytes = CGImageGetBytesPerRow(self.currentFrame.CGImage) * CGImageGetHeight(self.currentFrame.CGImage);
if (bytes == 0) bytes = 1024;

NSUInteger max = 0;
if (self.maxBufferSize > 0) {
max = self.maxBufferSize;
Expand All @@ -305,13 +294,13 @@ - (void)calculateMaxBufferCount
NSUInteger free = RCTDeviceFreeMemory();
max = MIN(total * 0.2, free * 0.6);
}

NSUInteger maxBufferCount = (double)max / (double)bytes;
if (!maxBufferCount) {
// At least 1 frame
maxBufferCount = 1;
}

self.maxBufferCount = maxBufferCount;
}

Expand Down

1 comment on commit abf612a

@letscms
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am using windows android. So how I will apply these changes on the windows

Please sign in to comment.