美文网首页iOS 知识点
iOS原理之Runtime-__weak的实现原理

iOS原理之Runtime-__weak的实现原理

作者: yqc5521 | 来源:发表于2019-05-22 15:46 被阅读0次
    //
    //  RuntimeBasement__weekViewController.swift
    //  iOS底层
    //
    //  Created by yanqunchao on 2019/5/21.
    //  Copyright © 2019 yanqunchao. All rights reserved.
    //
    
    import UIKit
    
    let WEAK_INLINE_COUNT = 4
    
    class RuntimeBasement__weekViewController: UIViewController {
      
        class WeakEntryT:NSObject {
            var referent:NSObject? // 被弱引用的对象
            
            var inline_referrers: [UnsafeMutablePointer<NSObject>?] = [UnsafeMutablePointer<NSObject>?](repeating: nil, count: WEAK_INLINE_COUNT)
            init(newReferent:NSObject,newReferrer:UnsafeMutablePointer<NSObject>) {
                print("【创建】新的弱引用入口")
                self.referent = newReferent
                inline_referrers[0] = newReferrer
                inline_referrers[0]?.pointee = newReferent
                for i in 1..<WEAK_INLINE_COUNT{
                    inline_referrers[i] = nil;
                }
            }
        }
        class RefcountMap:NSObject {
            
        }
        
        class WeakTableT:NSObject {
            var weakEntries:[WeakEntryT?] = [WeakEntryT?](repeating: nil, count: 4)
            var mask:Int?
        }
        
        class SideTable {
            var recnts:RefcountMap?
            var weak_table: WeakTableT?
            
            init() {
                self.weak_table = WeakTableT()
            }
            class func lockTwo(oldTable:SideTable,newTable:SideTable){}
            class func unlockTwo(oldTable:SideTable,newTable:SideTable){}
        };
        
        class objc_object:NSObject {
           
        };
        
        //存储所有弱引用的散列表
        lazy var SideTables : [SideTable] = {
            var sideTables:[SideTable]  = []
            for i in 0..<64{
              sideTables.append(SideTable())
            }
            return sideTables
        }() //初始化64个元素大小的SideTables数组
      
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = .white
            
            
            let obj1 = NSObject()
            let obj2 = NSObject()
            weak var weakObj1:NSObject? = obj1
            weak var weakObj2:NSObject? = obj2
     
            _ =  storeWeak(location: &weakObj1!, newObj: obj1)
            _ =  storeWeak(location: &weakObj2!, newObj: obj1)
            _ =  storeWeak(location: &weakObj1!, newObj: obj2)
            
            let sideTable = side_table_for_referent(referent: obj1)
            weak_clear_no_lock(weakTable: sideTable!.weak_table!, referent: obj1)
            
            let sideTable2 = side_table_for_referent(referent: obj2)
            weak_clear_no_lock(weakTable: sideTable2!.weak_table!, referent: obj2)
        }
        
    
        func printLocation(location:UnsafeMutablePointer<Any>) {
            print("\(location)")
        }
       
        func storeWeak(location:UnsafeMutablePointer<NSObject>,  newObj:NSObject) -> NSObject?
        {
            let sideTable = side_table_for_referent(referent: newObj)
    //        // 加锁操作,防止多线程中竞争冲突
    //        SideTable.lockTwo(oldTable: oldTable!, newTable: newTable!)
           
            if isOld(location: location) {
                print("【注销】旧的弱引用指针指向的对象")
                weak_unregister_no_lock(weakTable: sideTable!.weak_table!, oldObj: newObj, location: location)
            }
            print("【注册】新的弱引用指针指向的对象")
            weak_register_no_lock(weakTable: sideTable!.weak_table!, newObj: newObj, location: location)
            
            return newObj
        }
        
        func isOld(location:UnsafeMutablePointer<NSObject>)->Bool {
            var isOld = false
            for sideTable in self.SideTables {
                for entry in sideTable.weak_table!.weakEntries {
                    if entry != nil {
                        isOld = referrerIsExsit(entry: entry!, newReferrer: location)
                        if isOld == true {
                            print("【存在】弱引用地址")
                            return true
                        }
                    }
                }
            }
            print("【不存在】弱引用地址")
            return false
        }
        
        
        func side_table_for_referent(referent:NSObject) -> SideTable?{
         
            let mask = SideTables.count - 1
            let begin = weakEntryHash(key: referent, mask: mask)!
            
           print("\r\n\r\n\r\n【筛选】到位置在第\(begin)的SideTable")
            return SideTables[begin]
        }
        //移除旧的弱引用
        func weak_unregister_no_lock(weakTable:WeakTableT,oldObj:NSObject,location:UnsafeMutablePointer<NSObject>){
            let entry = weak_entry_for_referent(weakTable: weakTable, referent: oldObj)
            if (entry != nil) {
                remove_referrer(entry: entry!, old_referrer: location)
            }
        }
        
        //添加新的弱引用
        func weak_register_no_lock(weakTable:WeakTableT,newObj:NSObject,location:UnsafeMutablePointer<NSObject>){
            
            var entry = weak_entry_for_referent(weakTable: weakTable, referent: newObj)
            
            let new_referrer = location
            if (entry != nil) { // 如果能找到weak_entry,则将referrer插入到weak_entry中
       
                append_referrer(entry: entry!, newReferrer: new_referrer);
            }
            else { // 如果找不到,就新建一个,并插入到weaktalbe的weakEntries数组里面
                entry = WeakEntryT(newReferent: newObj, newReferrer: new_referrer)
                weak_entry_insert(weak_table: weakTable, new_entry: entry!)
            }
        }
        
     func weak_clear_no_lock(weakTable:WeakTableT,referent:NSObject?)
        {
            let entry = weak_entry_for_referent(weakTable: weakTable, referent: referent!)
            if (entry == nil) {
                // XXX shouldn't happen, but does with mismatched CF/objc
                print("XXX no entry for clear deallocating\( referent!)")
                return
            }
      
            for referrer in entry!.inline_referrers {
                
                if referrer?.pointee == referent {
                    //弱引用地址指向的对象的置为空
    //                referrer?.pointee = nil
                    print("弱引用地址指向的对象的置为空")
                }
            }
            weak_entry_remove(weak_table: weakTable, entry: entry!)
        }
      
        
        func weak_entry_remove(weak_table:WeakTableT, entry:WeakEntryT) {
            //清空弱引用入口
            for (i,entry1) in weak_table.weakEntries.enumerated() {
                if entry1 == entry {
                   weak_table.weakEntries[i] = nil
                   return
                }
            }
        }
        
        func weak_entry_insert(weak_table:WeakTableT,new_entry:WeakEntryT) {
            var weak_entries = weak_table.weakEntries
            let mask = weak_entries.count - 1
            let begin = weakEntryHash(key: new_entry.referent!, mask: mask)
            var i = begin
            repeat {
                let weakEntry = weak_entries[i!]
                if weakEntry?.referent == nil{
                    print("【填充】新的入口到弱引用表中")
                    weak_entries[i!] = new_entry
                    weak_table.weakEntries = weak_entries
                    return
                }
                i = weakEntryNext(i: i!, mask: mask)
            }while(i != begin)
     
        }
        func weak_entry_for_referent(weakTable:WeakTableT,referent:NSObject) -> WeakEntryT?{
      
            let weakEntries = weakTable.weakEntries
            let mask = weakEntries.count - 1
            let begin = weakEntryHash(key: referent, mask: mask)
            
            var i = begin
            var runCount = 0
            
            repeat {
                let weakEntry = weakEntries[i!]
                if weakEntry?.referent == referent {
                    print("【找到】对应的弱引用入口")
                    return weakEntry
                }
                if runCount == mask + 1 { //跑一圈没找到
                    print("【没找到】对应的弱引用入口")
                    return nil
                }
                i = weakEntryNext(i: i!, mask: mask)
                runCount += 1
            }while(i != begin)
            print("【没找到】对应的弱引用入口")
            return nil
        }
        
        func weakEntryNext(i:Int,mask:Int) ->Int? {
            var index = i
            if index != 0 {
                index = index - 1
                return index
            }else {
                return mask
            }
        }
        
        
        func weakEntryHash(key:NSObject,mask:Int) ->Int? {
            let keyAddr = Unmanaged.passUnretained(key as AnyObject).toOpaque()
            let keyAddrStr = "\(keyAddr)"
            let lastKeyStr = keyAddrStr.suffix(keyAddrStr.count - 2)
            let keyInt = ConvertUtil.hexTodec(number: String(lastKeyStr))
            return keyInt & mask
        }
        
        //添加弱引用
        func append_referrer(entry:WeakEntryT,newReferrer:UnsafeMutablePointer<NSObject>){
            print("【添加】弱引用地址")
            for (i, referrer) in entry.inline_referrers.enumerated()  {
                if referrer == nil {
                    entry.inline_referrers[i] = newReferrer
                    entry.inline_referrers[i]?.pointee = entry.referent!
                    return
                }
            }
        }
     
        func remove_referrer(entry:WeakEntryT,old_referrer:UnsafeMutablePointer<NSObject>){
            print("【删除】弱引用地址")
            for (i, referrer) in entry.inline_referrers.enumerated()  {
                if referrer == old_referrer {
                    entry.inline_referrers[i] = nil
                    return
                }
            }
        }
        
        //inline_referrers是否存在referrr
        func referrerIsExsit(entry:WeakEntryT,newReferrer:UnsafeMutablePointer<NSObject>) -> Bool{
            
            for (i, referrer) in entry.inline_referrers.enumerated()  {
                if referrer == newReferrer{
                    //元素置为空
                    entry.inline_referrers[i] = nil
                    return true
                }
            }
            return false
        }  
    }
    

    相关文章

      网友评论

        本文标题:iOS原理之Runtime-__weak的实现原理

        本文链接:https://www.haomeiwen.com/subject/bkzyzqtx.html