臨下班前一位做引擎的小夥伴提了個小問題, Rocksdb 實作了非常多的Env backend
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CNxETN4cTNjZjMmBzM4QjNzYzX1EjMxETM0AzLcFTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
這一些backend 可以讓使用者根據自己需求建立不同 公共接口backend,來實作自己的檔案操作或者公共線程池操作。
Env* env = new rocksdb::HdfsEnv(FLAGS_hdfs)
問題是,為什麼Rocksdb 這裡又多實作了一個
EnvWrapper
類,
class EnvWrapper : public Env
,其将
Env
幾乎所有的成員函數都用預設方式overrie了一遍,有必要嗎?
因為
Env
的類中除了
Env* Default()
之外的函數成員很多都已經是純虛函數了,它已經可以作為一個抽象類,來用其子類初始化該Env就可以了,那實作的這個
EnvWrapper
中每一個函數都掉用一次
Env
基類 的對應實作完全沒有意義呀,想要實作自己的子類是不是隻需要繼承一下Env 基類就可以了,為什麼還需要單獨增加這兩百多行代碼?
大概看了一下 Rocksdb 内部是如何使用
EnvWrapper
的
可以看到有非常多的實作使用EnvWrapper,而在該類實作之前的注釋中可以很清晰得看到
EnvWrapper
的作用:
- 如果是隻有
Env
這個基類,那使用者實作自己的bakend 的時候就需要将裡面所有的純虛函數都實作一遍,這對很多使用者來說代價太高,有可能他們隻想修改其中一小部分函數,但卻要将所有的純虛函數override一遍。
比如這個
隻想要實作其中的幾個自己想用的函數就可以了,不需要受C++ 面向對象文法的限制了。NoSleepEnv
-
Rocksdb 官方在Env 中增加了一些非常有用的純虛函數,對于使用者來說(繼承EnvWrapper 的使用者),自己不需要修改任何代碼就可以直接使用。
比如,開發者在
基類中增加了一個Env
函數,同時同步到virtual Status DisablePageCache() = 0
中,這種情況下其他繼承自EnvWrapper
統一類的使用者不需要修改自己的任何代碼,就可以直接使用在這個函數。否則,直接繼承EnvWrapper
實作自己的類的話 任何Env的改動都需要使用者修改自己的代碼。Env